Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/EventGenerationRule.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/EventGenerationRule.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/EventGenerationRule.java	(revision 619)
@@ -0,0 +1,720 @@
+// Module    : $RCSfile: EventGenerationRule.java,v $
+// Version   : $Revision: 0.0 $  $Author: patrick $  $Date: 22.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by patrick
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jdom.Element;
+import org.jdom.Namespace;
+
+import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowsMessageType;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 22.08.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+class EventGenerationRule {
+
+    /**
+     * <p>
+     * the namespace used for parsing the rule
+     * </p>
+     */
+    private Namespace namespace;
+
+    /**
+     * <p>
+     * the name of the rule
+     * </p>
+     */
+    private String name;
+
+    /**
+     * <p>
+     * the list of conditions for the rule to be matched
+     * </p>
+     */
+    private List<MessageCondition> messageConditions;
+
+    /**
+     * <p>
+     * the list of parameters to be provided to the generated event
+     * </p>
+     */
+    private List<Term> eventParameters;
+
+    /**
+     * <p>
+     * the list of replay message generation rules
+     * </p>
+     */
+    private List<ReplayMessageSpec> replayMessageSpecifications;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param ruleElement
+     * @param rulesNamespace 
+     */
+    @SuppressWarnings("unchecked")
+    EventGenerationRule(Element ruleElement, Namespace rulesNamespace) {
+        this.namespace = rulesNamespace;
+        
+        this.name = ruleElement.getAttributeValue("name");
+        
+        this.messageConditions = new ArrayList<MessageCondition>();
+        this.eventParameters = new ArrayList<Term>();
+        this.replayMessageSpecifications = new ArrayList<ReplayMessageSpec>();
+        
+        for (Element child : (List<Element>) ruleElement.getChildren()) {
+            if ("msg".equals(child.getName()) && namespace.equals(child.getNamespace())) {
+                messageConditions.add(new MessageCondition(child));
+            }
+            else if ("idinfo".equals(child.getName()) && namespace.equals(child.getNamespace())) {
+                for (Element parameterElements : (List<Element>) child.getChildren()) {
+                    eventParameters.add(new Term(parameterElements));
+                }
+            }
+            else if ("genMsg".equals(child.getName()) && namespace.equals(child.getNamespace())) {
+                replayMessageSpecifications.add(new ReplayMessageSpec(child));
+            }
+            else if ("genMsgSeq".equals(child.getName()) && namespace.equals(child.getNamespace())) {
+                replayMessageSpecifications.add(new ReplayMessageSpec(child));
+            }
+            else {
+                throw new IllegalArgumentException
+                    ("the provided rules can not be parsed: unknown element " + child.getName());
+            }
+        }
+    }
+
+    /**
+     * @return the name
+     */
+    String getName() {
+        return name;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @return
+     */
+    List<MessageCondition> getMessageConditions() {
+        return messageConditions;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @return
+     */
+    List<Term> getEventParameters() {
+        return eventParameters;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @return
+     */
+    List<ReplayMessageSpec> getReplayMessageSpecifications() {
+        return replayMessageSpecifications;
+    }
+
+    /**
+     * <p>
+     * TODO comment
+     * </p>
+     * 
+     * @version $Revision: $ $Date: 22.08.2012$
+     * @author 2012, last modified by $Author: patrick$
+     */
+    class MessageCondition {
+
+        /**
+         * <p>
+         * true, if the condition defines to match several conditions
+         * </p>
+         */
+        private boolean matchMultiple;
+        
+        /**
+         * <p>
+         * the type of the message matched by the condition
+         * </p>
+         */
+        private WindowsMessageType messageType;
+
+        /**
+         * <p>
+         * the term conditions associate with the rule condition
+         * </p>
+         */
+        private List<AttributeCondition> attributeConditions;
+
+        /**
+         * <p>
+         * the list of messages to be stored, if the message matches, for continuing the
+         * rule application
+         * </p>
+         */
+        private ArrayList<Term> messagesToStore;
+
+        /**
+         * <p>
+         * TODO: comment
+         * </p>
+         *
+         * @param msgChild
+         */
+        @SuppressWarnings("unchecked")
+        private MessageCondition(Element msgChild) {
+            this.matchMultiple = "true".equals(msgChild.getAttributeValue("multiple"));
+            this.messageType =
+                WindowsMessageType.parseMessageType(msgChild.getAttributeValue("type"));
+            
+            this.attributeConditions = new ArrayList<AttributeCondition>();
+            for (Element childElement : (List<Element>) msgChild.getChildren("equals", namespace)) {
+                attributeConditions.add(new AttributeCondition(childElement));
+            }
+            
+            this.messagesToStore = new ArrayList<Term>();
+            for (Element childElement : (List<Element>) msgChild.getChildren("store", namespace)) {
+                messagesToStore.add(new Term(childElement));
+            }
+            for (Element childElement :
+                 (List<Element>) msgChild.getChildren("storeSeq", namespace))
+            {
+                messagesToStore.add(new Term(childElement));
+            }
+        }
+
+        /**
+         * @return the matchMultiple
+         */
+        boolean matchMultiple() {
+            return matchMultiple;
+        }
+
+        /**
+         * <p>
+         * TODO: comment
+         * </p>
+         *
+         * @return
+         */
+        WindowsMessageType getMessageType() {
+            return messageType;
+        }
+
+        /**
+         * <p>
+         * TODO: comment
+         * </p>
+         *
+         * @return
+         */
+        List<AttributeCondition> getAttributeConditions() {
+            return attributeConditions;
+        }
+
+        /**
+         * @return the valuesToStore
+         */
+        ArrayList<Term> getMessagesToStore() {
+            return messagesToStore;
+        }
+
+    }
+
+    /**
+     * <p>
+     * TODO comment
+     * </p>
+     * 
+     * @version $Revision: $ $Date: 22.08.2012$
+     * @author 2012, last modified by $Author: patrick$
+     */
+    class AttributeCondition {
+
+        /**
+         * <p>
+         * the left hand side of the condition
+         * </p>
+         */
+        private Term leftHandSide;
+        
+        /**
+         * <p>
+         * the left hand side of the condition
+         * </p>
+         */
+        private Term rightHandSide;
+
+        /**
+         * <p>
+         * TODO: comment
+         * </p>
+         *
+         * @param childElement
+         */
+        private AttributeCondition(Element conditionElement) {
+            this.leftHandSide = new Term((Element) conditionElement.getChildren().get(0));
+            this.rightHandSide = new Term((Element) conditionElement.getChildren().get(1));
+        }
+        
+        /**
+         * @return the leftHandSide
+         */
+        Term getLeftHandSide() {
+            return leftHandSide;
+        }
+
+        /**
+         * @return the rightHandSide
+         */
+        Term getRightHandSide() {
+            return rightHandSide;
+        }
+
+    }
+
+    /**
+     * <p>
+     * TODO comment
+     * </p>
+     * 
+     * @version $Revision: $ $Date: 22.08.2012$
+     * @author 2012, last modified by $Author: patrick$
+     */
+    class Term {
+
+        /**
+         * <p>
+         * the name of the term
+         * </p>
+         */
+        private String name;
+        
+        /**
+         * <p>
+         * the value of the term, if it is a constValue, null instead
+         * </p>
+         */
+        private String value;
+
+        /**
+         * <p>
+         * the variable name of the object, i.e. a message, of which a parameter is identified if
+         * the term is a winInfoValue or a msgInfoValue; null instead
+         * </p>
+         */
+        private String messageId;
+
+        /**
+         * <p>
+         * the name of the parameter of the object, e.g. a message, of which a parameter is
+         * identified if the term is a paramValue, null instead
+         * </p>
+         */
+        private String messageParameterName;
+
+        /**
+         * <p>
+         * the variable name of the message sequence denoted by the term in case of a seqValue;
+         * null instead
+         * </p>
+         */
+        private String sequenceId;
+
+        /**
+         * <p>
+         * the name of the parameter of the sequence of which a parameter is
+         * identified if the term is a seqValue, null instead
+         * </p>
+         */
+        private String sequenceParameterName;
+
+        /**
+         * <p>
+         * the name of the parameter of the window of the object, e.g. a message, of which a
+         * parameter is identified if the term is a winInfoValue, null instead
+         * </p>
+         */
+        private String windowParameterName;
+
+        /**
+         * <p>
+         * the name of the info of the message of which a parameter is identified if the
+         * term is a msgInfoValue, null instead
+         * </p>
+         */
+        private String messageInfoName;
+
+        /**
+         * <p>
+         * the name of the parameter of the message into which a value shall be stored if the
+         * term is a resolveHwnd, null instead
+         * </p>
+         */
+        private String storeParameterName;
+
+        /**
+         * <p>
+         * the list of handles to be resolved in case the term is a store or storeSeq, null instead
+         * </p>
+         */
+        private List<Term> resolveHandles;
+
+        /**
+         * <p>
+         * TODO: comment
+         * </p>
+         *
+         * @param object
+         */
+        @SuppressWarnings("unchecked")
+        private Term(Element termElement) {
+            this.name = termElement.getName();
+            
+            if ("constValue".equals(name)) {
+                this.value = termElement.getAttributeValue("value");
+            }
+            else if ("paramValue".equals(name)) {
+                this.messageId = termElement.getAttributeValue("obj");
+                this.messageParameterName = termElement.getAttributeValue("param");
+            }
+            else if ("winInfoValue".equals(name)) {
+                this.messageId = termElement.getAttributeValue("obj");
+                this.windowParameterName = termElement.getAttributeValue("winParam");
+            }
+            else if ("msgInfoValue".equals(name)) {
+                this.messageId = termElement.getAttributeValue("obj");
+                this.messageInfoName = termElement.getAttributeValue("msgParam");
+            }
+            else if ("seqValue".equals(name)) {
+                this.sequenceId = termElement.getAttributeValue("seqObj");
+                this.sequenceParameterName = termElement.getAttributeValue("param");
+            }
+            else if ("store".equals(name)) {
+                this.messageId = termElement.getAttributeValue("var");
+                if ((termElement.getChildren() != null) && (termElement.getChildren().size() > 0)) {
+                    this.resolveHandles = new ArrayList<Term>();
+                    for (Element child : (List<Element>) termElement.getChildren()) {
+                        this.resolveHandles.add(new Term(child));
+                    }
+                }
+            }
+            else if ("storeSeq".equals(name)) {
+                this.sequenceId = termElement.getAttributeValue("varSeq");
+                if ((termElement.getChildren() != null) && (termElement.getChildren().size() > 0)) {
+                    this.resolveHandles = new ArrayList<Term>();
+                    for (Element child : (List<Element>) termElement.getChildren()) {
+                        this.resolveHandles.add(new Term(child));
+                    }
+                }
+            }
+            else if ("resolveHwnd".equals(name)) {
+                this.messageParameterName = termElement.getAttributeValue("param");
+                this.storeParameterName = termElement.getAttributeValue("storeParam");
+            }
+        }
+
+        /**
+         * @return the name
+         */
+        String getName() {
+            return name;
+        }
+
+        /**
+         * @return the value
+         */
+        String getValue() {
+            return value;
+        }
+
+        /**
+         * @return the object
+         */
+        String getMessageId() {
+            return messageId;
+        }
+
+        /**
+         * @return the objectParameter
+         */
+        String getMessageParameterName() {
+            return messageParameterName;
+        }
+
+        /**
+         * @return the sequenceId
+         */
+        String getSequenceId() {
+            return sequenceId;
+        }
+
+        /**
+         * @return the sequenceParameter
+         */
+        String getSequenceParameterName() {
+            return sequenceParameterName;
+        }
+
+        /**
+         * @return the windowParameter
+         */
+        String getWindowParameterName() {
+            return windowParameterName;
+        }
+
+        /**
+         * @return the messageParameter
+         */
+        String getMessageInfoName() {
+            return messageInfoName;
+        }
+
+        /**
+         * @return the storeParameter
+         */
+        String getStoreParameterName() {
+            return storeParameterName;
+        }
+
+        /**
+         * @return the resolveHandles
+         */
+        List<Term> getResolveHandles() {
+            return resolveHandles;
+        }
+
+    }
+    
+    /**
+     * <p>
+     * TODO comment
+     * </p>
+     * 
+     * @version $Revision: $ $Date: 22.08.2012$
+     * @author 2012, last modified by $Author: patrick$
+     */
+    class ReplayMessageSpec {
+
+        /**
+         * <p>
+         * determines, if this specification defines one, or a sequence of messages
+         * </p>
+         */
+        private boolean generateSingleMessage;
+        
+        /**
+         * <p>
+         * the id of a concrete message of message sequence to be replayed as is
+         * </p>
+         */
+        private String replayObjectId;
+
+        private Term type;
+
+        private Term target;
+
+        private Term lparamLoWord;
+
+        private Term lparamHiWord;
+
+        private Term lparam;
+
+        private Term wparamLoWord;
+
+        private Term wparamHiWord;
+
+        private Term wparam;
+
+        private int delay;
+        
+        /**
+         * <p>
+         * TODO: comment
+         * </p>
+         *
+         * @param child
+         */
+        @SuppressWarnings("unchecked")
+        private ReplayMessageSpec(Element replayMessageSpecElement) {
+            List<Element> children = replayMessageSpecElement.getChildren();
+            if ("genMsg".equals(replayMessageSpecElement.getName())) {
+                generateSingleMessage = true;
+                if (children.size() == 1) {
+                    replayObjectId = children.get(0).getAttributeValue("obj");
+                }
+            }
+            else {
+                generateSingleMessage = false;
+                if (children.size() == 1) {
+                    replayObjectId = children.get(0).getAttributeValue("seqObj");
+                }
+            }
+            
+            this.delay = Integer.parseInt(replayMessageSpecElement.getAttributeValue("delay"));
+            
+            if (children.size() > 1) {
+                for (Element child : children) {
+                    Element termElement = (Element) child.getChildren().get(0);
+                    
+                    if (child.getName().equals("type")) {
+                        this.type = new Term(termElement);
+                    }
+                    else if (child.getName().equals("target")) {
+                        this.target = new Term(termElement);
+                        
+                        if (!generateSingleMessage) {
+                            // in this case, the target is always a sequence value term, i.e.
+                            // the targets of the originally recorded sequence. So the
+                            // replay object id is set to this sequence
+                            replayObjectId = target.getSequenceId();
+                        }
+                    }
+                    else if (child.getName().equals("LPARAM")) {
+                        Element loWordElement = child.getChild("LOWORD", namespace);
+                        if (loWordElement != null) {
+                            this.lparamLoWord =
+                                new Term((Element) loWordElement.getChildren().get(0));
+                        }
+                        
+                        Element hiWordElement = child.getChild("HIWORD", namespace);
+                        if (hiWordElement != null) {
+                            this.lparamHiWord =
+                                 new Term((Element) hiWordElement.getChildren().get(0));
+                        }
+                        
+                        if ((lparamLoWord == null) && (lparamHiWord == null)) {
+                            this.lparam = new Term(termElement);
+                        }
+                    }
+                    else if (child.getName().equals("WPARAM")) {
+                        Element loWordElement = child.getChild("LOWORD", namespace);
+                        if (loWordElement != null) {
+                            this.wparamLoWord =
+                                new Term((Element) loWordElement.getChildren().get(0));
+                        }
+                        
+                        Element hiWordElement = child.getChild("HIWORD", namespace);
+                        if (hiWordElement != null) {
+                            this.wparamHiWord =
+                                 new Term((Element) hiWordElement.getChildren().get(0));
+                        }
+                        
+                        if ((wparamLoWord == null) && (wparamHiWord == null)) {
+                            this.wparam = new Term(termElement);
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * <p>
+         * TODO: comment
+         * </p>
+         *
+         * @return
+         */
+        boolean generateSingleMessage() {
+            return generateSingleMessage;
+        }
+
+        /**
+         * <p>
+         * TODO: comment
+         * </p>
+         *
+         * @return
+         */
+        String getReplayObjectId() {
+            return replayObjectId;
+        }
+
+        /**
+         * @return the type
+         */
+        Term getType() {
+            return type;
+        }
+
+        /**
+         * @return the target
+         */
+        Term getTarget() {
+            return target;
+        }
+
+        /**
+         * @return the lparamLoWord
+         */
+        Term getLparamLoWord() {
+            return lparamLoWord;
+        }
+
+        /**
+         * @return the lparamHiWord
+         */
+        Term getLparamHiWord() {
+            return lparamHiWord;
+        }
+
+        /**
+         * @return the lparam
+         */
+        Term getLparam() {
+            return lparam;
+        }
+
+        /**
+         * @return the wparamLoWord
+         */
+        Term getWparamLoWord() {
+            return wparamLoWord;
+        }
+
+        /**
+         * @return the wparamHiWord
+         */
+        Term getWparamHiWord() {
+            return wparamHiWord;
+        }
+
+        /**
+         * @return the wparam
+         */
+        Term getWparam() {
+            return wparam;
+        }
+
+        /**
+         * @return the delay
+         */
+        int getDelay() {
+            return delay;
+        }
+
+    }
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/EventGenerator.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/EventGenerator.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/EventGenerator.java	(revision 619)
@@ -1,6 +1,8 @@
+
 package de.ugoe.cs.quest.plugin.mfc;
 
 import java.io.IOException;
 import java.security.InvalidParameterException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -18,15 +20,19 @@
 
 import de.ugoe.cs.quest.eventcore.Event;
-import de.ugoe.cs.quest.plugin.mfc.eventcore.MFCEventTarget;
-import de.ugoe.cs.quest.plugin.mfc.eventcore.MFCEventType;
-import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowTree;
-import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowTreeNode;
+import de.ugoe.cs.quest.eventcore.IEventType;
+import de.ugoe.cs.quest.plugin.mfc.EventGenerationRule.Term;
+import de.ugoe.cs.quest.plugin.mfc.eventcore.MFCEvent;
+import de.ugoe.cs.quest.plugin.mfc.eventcore.MFCEventTypeFactory;
+import de.ugoe.cs.quest.plugin.mfc.eventcore.ReplayWindowsMessage;
 import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowsMessage;
+import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowsMessageType;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.MFCGUIElement;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.WindowTree;
 import de.ugoe.cs.util.console.Console;
 
 /**
  * <p>
- * Translates sequences of windows messages into {@link WindowsEvent}s that can
- * be used by the EventBench core libraries.
+ * Translates sequences of windows messages into {@link WindowsEvent}s that can be used by the
+ * EventBench core libraries.
  * </p>
  * 
@@ -36,966 +42,1069 @@
 public class EventGenerator {
 
-	/**
-	 * <p>
-	 * Helper method that fetches the document node of an XML file.
-	 * </p>
-	 * 
-	 * @param filename
-	 *            name of the XML file
-	 * @return the document node
-	 */
-	private static Document getDocument(String filename) {
-		SAXBuilder builder = new SAXBuilder();
-		Document doc = null;
-
-		try {
-			doc = builder.build(filename);
-			rulesNamespace = Namespace.getNamespace("ul:rules");
-		} catch (JDOMException e) {
-			Console.printerrln("Invalid rules file.");
-			e.printStackTrace();
-		} catch (IOException e) {
-			Console.printerrln("Invalid rules file.");
-			e.printStackTrace();
-		}
-
-		return doc;
-	}
-
-	/**
-	 * <p>
-	 * Name and path of the XML files containing the rules.
-	 * </p>
-	 */
-	private String rulesFile;
-
-	/**
-	 * <p>
-	 * Iterator used for the current sequence.
-	 * </p>
-	 */
-	private ListIterator<WindowsMessage> sequenceIterator;
-
-	/**
-	 * <p>
-	 * Token that is currently being generated.
-	 * </p>
-	 */
-	private Event currentToken;
-	
-	/**
-	 * <p>
-	 * Event type of the current token. Stored as a member to be able to update it during the parsing of the idinfo tag.
-	 * </p>
-	 */
-	private MFCEventType currentType;
-
-	/**
-	 * <p>
-	 * Reference to the ul:rules namespace.
-	 * </p>
-	 */
-	private static Namespace rulesNamespace;
-
-	/**
-	 * <p>
-	 * The name of the rule that is currently being evaluated.
-	 * </p>
-	 */
-	private String currentRuleName;
-
-	/**
-	 * <p>
-	 * Internal message storage. Used to implement the
-	 * <code>{@literal <store>}</code> and <code>{@literal <storeSeq>}</code>
-	 * tags.
-	 * </p>
-	 */
-	private Map<String, Object> messageStorage;
-
-	/**
-	 * <p>
-	 * Creates a new EventGenerator. Sets "data/rules.xml" as default file for
-	 * the rules.
-	 * </p>
-	 */
-	public EventGenerator() {
-		rulesFile = "data/rules.xml";
-	}
-
-	/**
-	 * <p>
-	 * Tries to match the rules to the given sequence to generate an
-	 * {@link WindowsEvent}.
-	 * </p>
-	 * <p>
-	 * The rules are matched the order, in which they are defined in the XML
-	 * file. Therefore, the order of the rules in the file defines priorities,
-	 * when multiple rules could be matched to the same sequence.
-	 * </p>
-	 * 
-	 * @param sequence
-	 *            sequence of message for which an event will be generated
-	 * @return event that matches the messages; null, if no rule can be matched
-	 */
-	@SuppressWarnings("unchecked")
-	public Event generateEvent(List<WindowsMessage> sequence) {
-		Document rulesDoc = getDocument(rulesFile);
-		Element rulesRoot = rulesDoc.getRootElement();
-
-		List<Element> ruleElements = rulesRoot.getChildren("rule",
-				rulesNamespace);
-
-		boolean isMatch = false;
-
-		for (int ruleIndex = 0; ruleIndex < ruleElements.size() && !isMatch; ruleIndex++) {
-			Element currentRule = ruleElements.get(ruleIndex);
-			currentRuleName = currentRule.getAttributeValue("name");
-			currentType = new MFCEventType(currentRuleName);
-			currentToken = new Event(currentType);
-			
-			isMatch = true;
-			messageStorage = new HashMap<String, Object>();
-			sequenceIterator = sequence.listIterator();
-			List<Element> ruleChildrenMsg = currentRule.getChildren("msg",
-					rulesNamespace);
-
-			int i = 0;
-			while (isMatch && i < ruleChildrenMsg.size()) {
-				Element messageElement = ruleChildrenMsg.get(i);
-				if ("true".equals(messageElement.getAttributeValue("multiple"))) {
-					Element nextMessageElement = null;
-					if (i + 1 < ruleChildrenMsg.size()) {
-						nextMessageElement = ruleChildrenMsg.get(i + 1);
-					}
-					try {
-						isMatch = matchMultipleMessages(messageElement,
-								nextMessageElement);
-					} catch (InvalidParameterException e) {
-						Console.printerrln(e.getMessage());
-					}
-				} else {
-					try {
-						isMatch = matchSingleMessage(messageElement);
-					} catch (InvalidParameterException e) {
-						Console.printerrln(e.getMessage());
-					}
-				}
-				i++;
-			}
-			if (isMatch) {
-				List<Element> ruleChildren = currentRule.getChildren();
-				for (Element genMsgElement : ruleChildren) {
-					if (genMsgElement.getName().equals("genMsg")) {
-						try {
-							generateReplayMessage(genMsgElement);
-						} catch (InvalidParameterException e) {
-							Console.printerrln(e.getMessage());
-							// TODO currentToken.invalidateReplay();
-						}
-					} else if (genMsgElement.getName().equals("genMsgSeq")) {
-						try {
-							generateReplaySequence(genMsgElement);
-							// TODO currentToken.invalidateReplay();
-						} catch (InvalidParameterException e) {
-							Console.printerrln(e.getMessage());
-							// TODO currentToken.invalidateReplay();
-						}
-					}
-				}
-				Element idinfoElement = currentRule.getChild("idinfo",
-						rulesNamespace);
-				if (idinfoElement != null) {
-					// cannot be empty if document is valid
-					List<Element> valueElements = idinfoElement.getChildren();
-					currentType.setInfo(getTermValue(null,
-							valueElements.get(0)));
-				}
-				Console.traceln(currentToken.getType().toString() + " matched");
-			} else {
-				currentToken = null;
-			}
-		}
-		if (!isMatch) {
-			Console.traceln("no match found for sequence: "
-					+ sequence.toString());
-		}
-		return currentToken;
-	}
-
-	// ////////////////////////////////////////////////////////////
-	// Helper functions for matching of events, i.e., msg-nodes //
-	// ////////////////////////////////////////////////////////////
-
-	/**
-	 * <p>
-	 * Handles msg-nodes where multiple is not true, i.e., not a sequences.
-	 * </p>
-	 * 
-	 * @param messageElement
-	 *            {@link Element} representing the msg-node
-	 * @return true, if a match is found; false otherwise
-	 */
-	private boolean matchSingleMessage(Element messageElement) {
-		boolean isMatch = false;
-		WindowsMessage currentMessage = null;
-
-		int type = Integer.parseInt(messageElement.getAttributeValue("type"));
-
-		while (!isMatch && sequenceIterator.hasNext()) {
-			/*
-			 * traverses the messages from the current position forward till a
-			 * message with the correct type is found
-			 */
-			currentMessage = sequenceIterator.next();
-			if (type == currentMessage.getType()) {
-				// message with the correct type found
-				// eval child nodes for further matching/storing
-				isMatch = evalEqualRestrictions(currentMessage, messageElement);
-
-				// in case the message is a match, eval storage children
-				if (isMatch) {
-					handleStorage(messageElement, currentMessage);
-					currentToken.setTarget(new MFCEventTarget(currentMessage
-							.getXmlWindowDescription()));
-					// TODO currentToken.setTargetShort(currentMessage.getParentNames());
-				}
-			}
-		}
-
-		return isMatch;
-	}
-
-	/**
-	 * <p>
-	 * Handles msg-nodes where multiple is true, i.e., sequences. Requires
-	 * knowledge about the next msg-node to determine the end of the sequence.
-	 * </p>
-	 * 
-	 * @param messageElement
-	 *            {@link Element} representing the msg-node
-	 * @param nextMessageElement
-	 *            {@link Element} representing the next msg-node; {@code null}
-	 *            if the current node is the last one
-	 * @return true, if a sequence is matched; false otherwise
-	 */
-	private boolean matchMultipleMessages(Element messageElement,
-			Element nextMessageElement) {
-		boolean isMatch = false;
-		boolean isCurrentMatch = false;
-		boolean nextMatchFound = false;
-		WindowsMessage currentMessage = null;
-		WindowsMessage nextMessage = null;
-
-		int type = Integer.parseInt(messageElement.getAttributeValue("type"));
-
-		int nextType = -1;
-		if (nextMessageElement != null) {
-			nextType = Integer.parseInt(nextMessageElement
-					.getAttributeValue("type"));
-		}
-
-		while (!nextMatchFound && sequenceIterator.hasNext()) {
-			currentMessage = sequenceIterator.next();
-			if (type == currentMessage.getType()) {
-				isCurrentMatch = evalEqualRestrictions(currentMessage,
-						messageElement);
-				isMatch = isMatch || isCurrentMatch;
-
-				if (isCurrentMatch) {
-					handleStorage(messageElement, currentMessage);
-					currentToken.setTarget(new MFCEventTarget(currentMessage
-							.getXmlWindowDescription()));
-					// TODO currentToken.setTargetShort(currentMessage.getParentNames());
-				}
-			}
-			if (nextMessageElement != null && isMatch) {
-				// peek next message to check if the sequence ends and the next
-				// match is found
-				if (!sequenceIterator.hasNext()) {
-					return false; // sequence is over, but not all messages are
-									// found
-				}
-				nextMessage = sequenceIterator.next();
-				sequenceIterator.previous();
-
-				if (nextType == nextMessage.getType()) {
-					nextMatchFound = evalEqualRestrictions(nextMessage,
-							nextMessageElement);
-				}
-
-			}
-		}
-
-		return isMatch;
-	}
-
-	/**
-	 * <p>
-	 * Handles equals-nodes.
-	 * </p>
-	 * 
-	 * @param currentMessage
-	 *            {@link Element} representing the msg-node the equals-node
-	 *            belongs to
-	 * @param messageElement
-	 *            {@link Element} representing the equals-node to be evaluated
-	 * @return true, if constraint is fulfilled; false otherwise
-	 */
-	@SuppressWarnings("unchecked")
-	private boolean evalEqualRestrictions(WindowsMessage currentMessage,
-			Element messageElement) {
-		boolean isMatch = true;
-		for (Element childElement : (List<Element>) messageElement.getChildren(
-				"equals", rulesNamespace)) {
-			List<Element> termElements = childElement.getChildren();
-			// the size 2 of termElements is guaranteed by the XML schema
-			String value1 = getTermValue(currentMessage, termElements.get(0));
-			String value2 = getTermValue(currentMessage, termElements.get(1));
-			if (value1 == null || value2 == null) {
-				isMatch = false;
-			} else {
-				isMatch = isMatch && value1.equals(value2);
-			}
-		}
-		for (Element childElement : (List<Element>) messageElement.getChildren(
-				"equalsSeq", rulesNamespace)) {
-			List<Element> termElements = childElement.getChildren();
-			List<String> values1 = getTermValueSeq(termElements.get(0));
-			List<String> values2 = getTermValueSeq(termElements.get(0));
-			if (values1 == null || values2 == null) {
-				isMatch = false;
-			} else {
-				isMatch = isMatch && values1.equals(values2);
-			}
-		}
-		return isMatch;
-	}
-
-	/**
-	 * <p>
-	 * Handles store-nodes and storeSeq-nodes.
-	 * </p>
-	 * 
-	 * @param messageElement
-	 *            {@link Element} representing the msg-node that is currently
-	 *            being evaluated
-	 * @param currentMessage
-	 *            current message in the message sequence that is matched; this
-	 *            is the message that is stored
-	 */
-	@SuppressWarnings("unchecked")
-	private void handleStorage(Element messageElement,
-			WindowsMessage currentMessage) {
-		for (Element childElement : (List<Element>) messageElement.getChildren(
-				"store", rulesNamespace)) {
-			String identifier = childElement.getAttributeValue("var");
-			messageStorage.put(identifier, currentMessage);
-			resolveHwnd(currentMessage, childElement);
-		}
-		for (Element childElement : (List<Element>) messageElement.getChildren(
-				"storeSeq", rulesNamespace)) {
-			String identifier = childElement.getAttributeValue("varSeq");
-			Object tmp = messageStorage.get(identifier);
-			List<WindowsMessage> storedSequence;
-			if (tmp == null || tmp instanceof WindowsMessage) {
-				storedSequence = new LinkedList<WindowsMessage>();
-				storedSequence.add(currentMessage);
-				messageStorage.put(identifier, storedSequence);
-			} else if (tmp instanceof List<?>) {
-				storedSequence = (List<WindowsMessage>) tmp;
-				storedSequence.add(currentMessage);
-				messageStorage.put(identifier, storedSequence);
-			}
-			resolveHwnd(currentMessage, childElement);
-		}
-	}
-
-	/**
-	 * <p>
-	 * Resolves a parameter that contains a HWND of a message to the target
-	 * string of the HWND and stores it.
-	 * </p>
-	 * 
-	 * @param currentMessage
-	 *            message whose HWND is resolved
-	 * @param childElement
-	 *            child element of the store node that represents the resolve
-	 */
-	@SuppressWarnings("unchecked")
-	private void resolveHwnd(WindowsMessage currentMessage, Element childElement) {
-		List<Element> resolveElements = childElement.getChildren("resolveHwnd",
-				rulesNamespace);
-		for (Element resolveElement : resolveElements) {
-			String param = resolveElement.getAttributeValue("param");
-			String storeParam = resolveElement.getAttributeValue("storeParam");
-			int paramHwnd = Integer
-					.parseInt(currentMessage.getParameter(param));
-			WindowTreeNode node = WindowTree.getInstance().find(paramHwnd);
-			if (node != null) {
-				currentMessage.addParameter(storeParam,
-						node.xmlRepresentation());
-			}
-		}
-	}
-
-	// /////////////////////////////////////////////////////
-	// Helper functions for generating the replay, i.e.,
-	// parsing of genMsg und genMsgSeq-nodes
-	// /////////////////////////////////////////////////////
-
-	/**
-	 * <p>
-	 * Handles genMsg-nodes and adds the replay to the {@link Event} that is
-	 * generated.
-	 * </p>
-	 * 
-	 * @param genMsgElement
-	 *            {@link Element} representing the genMsg-node
-	 */
-	@SuppressWarnings("unchecked")
-	private void generateReplayMessage(Element genMsgElement) {
-		List<Element> genMsgChildren = genMsgElement.getChildren();
-		WindowsMessage generatedMessage = null;
-		if (genMsgChildren.size() == 1) { // replay stored message without
-											// change
-			String obj = genMsgChildren.get(0).getAttributeValue("obj");
-			generatedMessage = getStoredMessageVariable(null, obj);
-		} else { // generate message according to the rule
-			for (Element genMsgChild : genMsgChildren) {
-				Element termElement = (Element) genMsgChild.getChildren()
-						.get(0);
-				if (genMsgChild.getName().equals("type")) {
-					try {
-						int msgType = Integer.parseInt(getTermValue(null,
-								termElement));
-						generatedMessage = new WindowsMessage(msgType);
-					} catch (NumberFormatException e) {
-						throw new InvalidParameterException(
-								"Failure generating replay sequence for rule "
-										+ currentRuleName
-										+ ": Defined type is not an integer.");
-					}
-				} else if (genMsgChild.getName().equals("target")) {
-					String targetString = getTermValue(null, termElement);
-					generatedMessage.setXmlWindowDescription(targetString);
-				} else if (genMsgChild.getName().equals("LPARAM")) {
-					String paramValueStr = getTermValue(null, termElement);
-					long paramValue = 0;
-					Element loword = genMsgChild.getChild("LOWORD",
-							rulesNamespace);
-					if (loword != null) {
-						paramValue = loHiWord(genMsgChild);
-						generatedMessage.setLPARAM(paramValue);
-					} else {
-						try {
-							paramValue = Integer.parseInt(paramValueStr);
-							generatedMessage.setLPARAM(paramValue);
-						} catch (NumberFormatException e) {
-							generatedMessage
-									.setLPARAMasWindowDesc(paramValueStr);
-						}
-					}
-				} else if (genMsgChild.getName().equals("WPARAM")) {
-					String paramValueStr = getTermValue(null, termElement);
-					long paramValue = 0;
-					Element loword = genMsgChild.getChild("LOWORD",
-							rulesNamespace);
-					if (loword != null) {
-						paramValue = loHiWord(genMsgChild);
-						generatedMessage.setWPARAM(paramValue);
-					} else {
-						try {
-							paramValue = Integer.parseInt(paramValueStr);
-							generatedMessage.setWPARAM(paramValue);
-						} catch (NumberFormatException e) {
-							generatedMessage
-									.setWPARAMasWindowDesc(paramValueStr);
-						}
-					}
-				}
-			}
-		}
-		if (generatedMessage != null) {
-			int delay = Integer.parseInt(genMsgElement
-					.getAttributeValue("delay"));
-			generatedMessage.setDelay(delay);
-		} else {
-			// TODO currentToken.invalidateReplay();
-		}
-		currentToken.addReplayable(generatedMessage);
-	}
-
-	/**
-	 * Handles genMsgSeq-nodes and adds the replay to the {@link Event} that is
-	 * generated.</p>
-	 * 
-	 * @param genMsgElement
-	 *            {@link Element} representing the genMsgSeq-node.
-	 */
-	@SuppressWarnings("unchecked")
-	private void generateReplaySequence(Element genMsgElement) {
-		List<Element> genMsgSeqChildren = genMsgElement.getChildren();
-		List<WindowsMessage> generatedMessageSeq = new LinkedList<WindowsMessage>();
-		if (genMsgSeqChildren.size() == 1) {
-			String obj = genMsgSeqChildren.get(0).getAttributeValue("seqObj");
-			generatedMessageSeq = getStoredSeqVariable(obj);
-		} else {
-			boolean msgsGenerated = false;
-			int constMsgType = 0;
-			for (Element genMsgSeqChild : genMsgSeqChildren) {
-				Element termElement = (Element) genMsgSeqChild.getChildren()
-						.get(0);
-				if (genMsgSeqChild.getName().equals("type")) {
-					// note: cannot easily be extracted because of mulitple
-					// return values
-					if (termElement.getName().equals("seqValue")) {
-						String obj = termElement.getAttributeValue("seqObj");
-						List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
-						for (WindowsMessage msg : seqVar) {
-							generatedMessageSeq.add(new WindowsMessage(msg
-									.getType()));
-						}
-						msgsGenerated = true;
-					} else { // constValue type
-						constMsgType = Integer.parseInt(getTermValue(null,
-								termElement));
-					}
-				} else if (genMsgSeqChild.getName().equals("target")) {
-					msgsGenerated = createSequenceTarget(generatedMessageSeq,
-							msgsGenerated, constMsgType, termElement);
-				} else if (genMsgSeqChild.getName().equals("LPARAM")) {
-					msgsGenerated = createSequenceLParam(generatedMessageSeq,
-							msgsGenerated, constMsgType, termElement);
-				} else if (genMsgSeqChild.getName().equals("WPARAM")) {
-					msgsGenerated = createSequenceWParam(generatedMessageSeq,
-							msgsGenerated, constMsgType, termElement);
-				}
-			}
-		}
-		currentToken.addReplayableSequence(generatedMessageSeq);
-	}
-
-	/**
-	 * <p>
-	 * Creates the targets for replay sequences generated with genMsgSeq-nodes.
-	 * </p>
-	 * 
-	 * @param generatedMessageSeq
-	 *            list of the messages that is being generated
-	 * @param msgsGenerated
-	 *            boolean stating if the list of messages is already generated
-	 *            or if the generation has to be handles by this method
-	 * @param constMsgType
-	 *            a constant message type that is used for message generation,
-	 *            in case the list of message is generated by this method
-	 * @param termElement
-	 *            {@link Element} representing the term-node describing the
-	 *            target
-	 * @return true, if the list of message is generated after calling this
-	 *         method; false otherwise
-	 * @throws NoSuchElementException
-	 *             thrown if the seqVar referred to in the termElement contains
-	 *             a different number of messages than is contained in
-	 *             messageSeq
-	 */
-	private boolean createSequenceTarget(
-			List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
-			int constMsgType, Element termElement)
-			throws NoSuchElementException {
-		Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator();
-		if (termElement.getName().equals("seqValue")) {
-			String obj = termElement.getAttributeValue("seqObj");
-			List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
-			if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) {
-				throw new InvalidParameterException(
-						"Failure generating replay sequence for rule "
-								+ currentRuleName
-								+ ": One or more of the sequence variables used to generate a sequence have different lenghts.");
-			}
-			for (WindowsMessage msg : seqVar) {
-				WindowsMessage currentSeqMsg = getCurrentSeqMsg(
-						generatedMessageSeq, msgsGenerated, constMsgType,
-						seqIterator);
-				String targetString = msg.getParameter(termElement
-						.getAttributeValue("param"));
-				currentSeqMsg.setXmlWindowDescription(targetString);
-			}
-			msgsGenerated = true;
-		} else { // const value
-			throw new AssertionError("target must be a sequence variable!");
-			/*
-			 * If target would not be a variable, the message-elements could not
-			 * yet be created and the whole sequence might be broken. If this is
-			 * to be changed, createSequenceLParam and createSequenceWParam need
-			 * to be addepted, too.
-			 */
-		}
-		return msgsGenerated;
-	}
-
-	/**
-	 * <p>
-	 * Creates the LPARAMs for replay sequences generated with genMsgSeq-nodes.
-	 * </p>
-	 * 
-	 * @param generatedMessageSeq
-	 *            list of the messages that is being generated
-	 * @param msgsGenerated
-	 *            boolean stating if the list of messages is already generated
-	 *            or if the generation has to be handles by this method
-	 * @param constMsgType
-	 *            a constant message type that is used for message generation,
-	 *            in case the list of message is generated by this method
-	 * @param termElement
-	 *            {@link Element} representing the term-node describing the
-	 *            LPARAM
-	 * @return true, if the list of message is generated after calling this
-	 *         method; false otherwise
-	 * @throws NoSuchElementException
-	 *             thrown if the seqVar referred to in the termElement contains
-	 *             a different number of messages than is contained in
-	 *             messageSeq
-	 */
-	private boolean createSequenceLParam(
-			List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
-			int constMsgType, Element termElement)
-			throws NoSuchElementException {
-		Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator();
-		if (termElement.getName().equals("seqValue")) {
-			String obj = termElement.getAttributeValue("seqObj");
-			List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
-			if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) {
-				throw new InvalidParameterException(
-						"Failure generating replay sequence for rule "
-								+ currentRuleName
-								+ ": One or more of the sequence variables used to generate a sequence have different lenghts.");
-			}
-			for (WindowsMessage msg : seqVar) {
-				WindowsMessage currentSeqMsg = getCurrentSeqMsg(
-						generatedMessageSeq, msgsGenerated, constMsgType,
-						seqIterator);
-				String paramValueStr = msg.getParameter(termElement
-						.getAttributeValue("param"));
-				int paramValue = 0;
-				try {
-					paramValue = Integer.parseInt(paramValueStr);
-					currentSeqMsg.setLPARAM(paramValue);
-				} catch (NumberFormatException e) {
-					currentSeqMsg.setLPARAMasWindowDesc(paramValueStr);
-				}
-			}
-			if (seqIterator.hasNext()) {
-				// the first seq-var has a different number of elements than the
-				// current one
-				throw new NoSuchElementException();
-			}
-			msgsGenerated = true;
-		} else { // const value
-			int paramValue = Integer.parseInt(getTermValue(null, termElement));
-			while (seqIterator.hasNext()) {
-				seqIterator.next().setLPARAM(paramValue);
-			}
-		}
-		return msgsGenerated;
-	}
-
-	/**
-	 * <p>
-	 * Creates the WPARAMs for replay sequences generated with genMsgSeq-nodes.
-	 * </p>
-	 * 
-	 * @param generatedMessageSeq
-	 *            list of the messages that is being generated
-	 * @param msgsGenerated
-	 *            boolean stating if the list of messages is already generated
-	 *            or if the generation has to be handles by this method
-	 * @param constMsgType
-	 *            a constant message type that is used for message generation,
-	 *            in case the list of message is generated by this method
-	 * @param termElement
-	 *            {@link Element} representing the term-node describing the
-	 *            WPARAM
-	 * @return true, if the list of message is generated after calling this
-	 *         method; false otherwise
-	 * @throws NoSuchElementException
-	 *             thrown if the seqVar referred to in the termElement contains
-	 *             a different number of messages than is contained in
-	 *             messageSeq
-	 */
-	private boolean createSequenceWParam(
-			List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
-			int constMsgType, Element termElement)
-			throws NoSuchElementException {
-		Iterator<WindowsMessage> seqIterator = generatedMessageSeq.iterator();
-		if (termElement.getName().equals("seqValue")) {
-			String obj = termElement.getAttributeValue("seqObj");
-			List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
-			if (msgsGenerated && seqVar.size() != generatedMessageSeq.size()) {
-				throw new InvalidParameterException(
-						"Failure generating replay sequence for rule "
-								+ currentRuleName
-								+ ": One or more of the sequence variables used to generate a sequence have different lenghts.");
-			}
-			for (WindowsMessage msg : seqVar) {
-				WindowsMessage currentSeqMsg = getCurrentSeqMsg(
-						generatedMessageSeq, msgsGenerated, constMsgType,
-						seqIterator);
-				String paramValueStr = msg.getParameter(termElement
-						.getAttributeValue("param"));
-				int paramValue = 0;
-				try {
-					paramValue = Integer.parseInt(paramValueStr);
-					currentSeqMsg.setWPARAM(paramValue);
-				} catch (NumberFormatException e) {
-					currentSeqMsg.setWPARAMasWindowDesc(paramValueStr);
-				}
-			}
-			if (seqIterator.hasNext()) {
-				// the first seq-var has a different number of elements than the
-				// current one
-				throw new NoSuchElementException();
-			}
-			msgsGenerated = true;
-		} else { // const value
-			int paramValue = Integer.parseInt(getTermValue(null, termElement));
-			while (seqIterator.hasNext()) {
-				seqIterator.next().setWPARAM(paramValue);
-			}
-		}
-		return msgsGenerated;
-	}
-
-	/**
-	 * <p>
-	 * If a message sequence is already generated, i.e., msgsGenerated is true,
-	 * the seqIterator is used to iterate through these messages and return the
-	 * current one. If the message sequence is not yet generated, i.e.,
-	 * msgsGenerated is false, the message sequence is generated on the fly
-	 * during each call of this message and the newly generated messages are
-	 * returned.
-	 * </p>
-	 * 
-	 * @param generatedMessageSeq
-	 *            message sequence
-	 * @param msgsGenerated
-	 *            indicates if generatedMessageSeq is already generated or has
-	 *            to be generated on the fly by this method
-	 * @param constMsgType
-	 *            type of the message to be used for message generation
-	 * @param seqIterator
-	 *            iterates through an already generated message sequence; must
-	 *            not be {@code null}, if msgsGenerated is true
-	 * @return current message
-	 */
-	private WindowsMessage getCurrentSeqMsg(
-			List<WindowsMessage> generatedMessageSeq, boolean msgsGenerated,
-			int constMsgType, Iterator<WindowsMessage> seqIterator) {
-		WindowsMessage currentSeqMsg = null;
-		if (msgsGenerated) {
-			currentSeqMsg = seqIterator.next();
-		} else {
-			currentSeqMsg = new WindowsMessage(constMsgType);
-			generatedMessageSeq.add(currentSeqMsg);
-		}
-		return currentSeqMsg;
-	}
-
-	// ////////////////////////////
-	// General helper functions //
-	// ////////////////////////////
-
-	/**
-	 * <p>
-	 * Retrieves a message from the storage for, e.g., comparison or replay.
-	 * "this" is used to refer to the current message.
-	 * </p>
-	 * 
-	 * @param currentMessage
-	 *            current message during the parsing; passed to handle "this"
-	 * @param obj
-	 *            object identifier in the storage
-	 * @return message retrieved from the storage
-	 * @throws InvalidParameterException
-	 *             thrown in case of invalid uses of "this" or if no message
-	 *             with the identifier obj is found in the storage
-	 */
-	private WindowsMessage getStoredMessageVariable(
-			WindowsMessage currentMessage, String obj)
-			throws InvalidParameterException {
-		WindowsMessage varMessage = null;
-		if (obj.equals("this")) {
-			if (currentMessage == null) {
-				throw new InvalidParameterException(
-						"Failure obtaining term value for rule "
-								+ currentRuleName
-								+ ": \"this\" is not a valid name for generating runtime messages.");
-			}
-			varMessage = currentMessage;
-		} else {
-			Object tmp = messageStorage.get(obj);
-			if (tmp instanceof WindowsMessage) {
-				varMessage = (WindowsMessage) tmp;
-			} else {
-				throw new InvalidParameterException(
-						"Failure obtaining term value for rule "
-								+ currentRuleName + ": No message \"" + obj
-								+ "\" stored.");
-			}
-		}
-		return varMessage;
-	}
-
-	/**
-	 * <p>
-	 * Retrieves a stored message sequence from the storage.
-	 * </p>
-	 * 
-	 * @param obj
-	 *            object identifier in the storage
-	 * @return message sequence retrieved from the storage
-	 * @throws InvalidParameterException
-	 *             thrown if no message sequences with the identifier obj is
-	 *             found in the storage
-	 */
-	@SuppressWarnings("unchecked")
-	private List<WindowsMessage> getStoredSeqVariable(String obj)
-			throws InvalidParameterException {
-		List<WindowsMessage> varMsgSeq = null;
-		Object tmp = messageStorage.get(obj);
-		if (tmp instanceof List<?>) {
-			varMsgSeq = (List<WindowsMessage>) tmp;
-		} else {
-			throw new InvalidParameterException(
-					"Failure obtaining term value for rule " + currentRuleName
-							+ ": No sequence \"" + obj + "\" store.");
-		}
-		return varMsgSeq;
-	}
-
-	/**
-	 * <p>
-	 * Handles term-nodes and returns the value of the described term.
-	 * </p>
-	 * 
-	 * @param currentMessage
-	 *            current message during the parsing; required to resolve
-	 *            references to "this" in a term
-	 * @param termElement
-	 *            {@link Element} representing the term node
-	 * @return value of the term or {@code null} of the term node could not be
-	 *         evaluated
-	 */
-	private String getTermValue(WindowsMessage currentMessage,
-			Element termElement) {
-		String value = null;
-		WindowsMessage varMessage = null;
-		if (termElement.getName().equals("constValue")) {
-			value = termElement.getAttributeValue("value");
-		} else if (termElement.getName().equals("paramValue")) {
-			String objectName = termElement.getAttributeValue("obj");
-			varMessage = getStoredMessageVariable(currentMessage, objectName);
-			if (varMessage != null) {
-				String param = termElement.getAttributeValue("param");
-				value = varMessage.getParameter(param);
-			}
-		} else if (termElement.getName().equals("winInfoValue")) {
-			String objectName = termElement.getAttributeValue("obj");
-			varMessage = getStoredMessageVariable(currentMessage, objectName);
-			if (varMessage != null) {
-				String paramString = termElement.getAttributeValue("winParam");
-				if (paramString.equals("class")) {
-					value = varMessage.getWindowClass();
-				} else if (paramString.equals("resourceId")) {
-					value = "" + varMessage.getWindowResourceId();
-				} else if (paramString.equals("hwnd")) {
-					value = "" + varMessage.getHwnd();
-				} else if (paramString.equals("parentTarget")) {
-					String target = varMessage.getXmlWindowDescription();
-					int index = target.lastIndexOf("<");
-					if (index == 0) {
-						Console.traceln("Trying to adress parent of top-level window! Replay probably invalid!");
-					}
-					value = target.substring(0, index);
-				} else if (paramString.equals("parentClass")) {
-					value = varMessage.getParentClass();
-				}
-			}
-		} else if (termElement.getName().equals("msgInfoValue")) {
-			String objectName = termElement.getAttributeValue("obj");
-			varMessage = getStoredMessageVariable(currentMessage, objectName);
-			if (varMessage != null) {
-				String paramString = termElement.getAttributeValue("msgParam");
-				if (paramString.equals("type")) {
-					value = "" + varMessage.getType();
-				} else if (paramString.equals("target")) {
-					value = varMessage.getXmlWindowDescription();
-				}
-			}
-		}
-		return value;
-	}
-
-	/**
-	 * <p>
-	 * Handles term-nodes contained by equalSeq nodes.
-	 * </p>
-	 * 
-	 * @param termElement
-	 *            {@link Element} representing the term-node
-	 * @return list of values of the term
-	 */
-	private List<String> getTermValueSeq(Element termElement) {
-		List<String> values = new LinkedList<String>();
-		if (termElement.getName().equals("seqValue")) {
-			String obj = termElement.getAttributeValue("seqObj");
-			String param = termElement.getAttributeValue("param");
-			List<WindowsMessage> seqVar = getStoredSeqVariable(obj);
-
-			for (WindowsMessage msg : seqVar) {
-				// msg.getParameter returns null, if parameter is not found,
-				// therefore the List can contain null-values
-				values.add(msg.getParameter(param));
-			}
-		}
-		return values;
-	}
-
-	/**
-	 * <p>
-	 * Handles LOWORD and HIWORD child nodes of LPARAM and WPARAM nodes. The
-	 * returned value is the LPARAM/WPARAM value based on the LOWORD and HIWORD.
-	 * </p>
-	 * 
-	 * @param param
-	 *            {@link Element} representing the LPARAM/WPARAM node
-	 * @return value of the LPARAM/WPARAM
-	 */
-	private long loHiWord(Element param) {
-		Element loword = param.getChild("LOWORD", rulesNamespace);
-		Element hiword = param.getChild("HIWORD", rulesNamespace);
-		String lowordStr = getTermValue(null, (Element) loword.getChildren()
-				.get(0));
-		String hiwordStr = getTermValue(null, (Element) hiword.getChildren()
-				.get(0));
-		return MAKEPARAM(Short.parseShort(lowordStr),
-				Short.parseShort(hiwordStr));
-	}
-
-	/**
-	 * <p>
-	 * Takes to short integers and combines them into the high and low order
-	 * bits of an integer.
-	 * </p>
-	 * 
-	 * @param loword
-	 *            low word
-	 * @param hiword
-	 *            high word
-	 * @return combined integer
-	 */
-	private static int MAKEPARAM(short loword, short hiword) {
-		return loword | ((int) hiword) << Short.SIZE;
-	}
+    /**
+     * <p>
+     * the list of all event generation rules available
+     * </p>
+     */
+    private List<EventGenerationRule> generationRules;
+    
+    /**
+     * <p>
+     * Name and path of the XML files containing the rules.
+     * </p>
+     */
+    private String rulesFile;
+
+    /**
+     * <p>
+     * Iterator used for the current sequence.
+     * </p>
+     */
+    private ListIterator<WindowsMessage> sequenceIterator;
+
+    /**
+     * <p>
+     * Token that is currently being generated.
+     * </p>
+     */
+    private MFCEvent currentEvent;
+
+    /**
+     * <p>
+     * Event type of the current token. Stored as a member to be able to update it during the
+     * parsing of the idinfo tag.
+     * </p>
+     */
+    private IEventType currentType;
+
+    /**
+     * <p>
+     * 
+     * </p>
+     */
+    private MFCGUIElement currentTarget;
+
+    /**
+     * <p>
+     * Reference to the ul:rules namespace.
+     * </p>
+     */
+    private static Namespace rulesNamespace;
+
+    /**
+     * <p>
+     * The name of the rule that is currently being evaluated.
+     * </p>
+     */
+    private String currentRuleName;
+
+    /**
+     * <p>
+     * Internal message storage. Used to implement the <code>{@literal <store>}</code> and
+     * <code>{@literal <storeSeq>}</code> tags.
+     * </p>
+     */
+    private Map<String, Object> messageStorage;
+
+    /**
+     * <p>
+     * reference to the window tree created during parsing
+     * </p>
+     */
+    private WindowTree windowTree;
+
+    /**
+     * <p>
+     * Creates a new EventGenerator. Sets "data/rules.xml" as default file for the rules.
+     * </p>
+     */
+    public EventGenerator(WindowTree windowTree) {
+        rulesFile = "data/rules.xml";
+        this.windowTree = windowTree;
+    }
+
+    /**
+     * <p>
+     * Tries to match the rules to the given sequence to generate an {@link WindowsEvent}.
+     * </p>
+     * <p>
+     * The rules are matched the order, in which they are defined in the XML file. Therefore, the
+     * order of the rules in the file defines priorities, when multiple rules could be matched to
+     * the same sequence.
+     * </p>
+     * 
+     * @param sequence
+     *            sequence of message for which an event will be generated
+     * @return event that matches the messages; null, if no rule can be matched
+     */
+    public Event generateEvent(List<WindowsMessage> sequence) {
+        if (generationRules == null) {
+            parseGenerationRules();
+        }
+        
+        
+        /*System.out.println("generating event for ");
+        for (WindowsMessage msg : sequence) {
+            System.out.println("    " + msg + "  " + msg.getParameter("scrollBarHandle") + "  " + msg.getTargetXML());
+        }*/
+
+        boolean isMatch = false;
+
+        for (int ruleIndex = 0; ruleIndex < generationRules.size() && !isMatch; ruleIndex++) {
+            EventGenerationRule currentRule = generationRules.get(ruleIndex);
+            currentRuleName = currentRule.getName();
+            
+            //System.out.println("checking rule " + currentRuleName);
+            
+            messageStorage = new HashMap<String, Object>();
+            sequenceIterator = sequence.listIterator();
+            
+            isMatch = evaluateMessageConditions(currentRule);
+
+            if (isMatch) {
+                currentType = MFCEventTypeFactory.getInstance().getEventType
+                    (currentRuleName, resolveParameters(currentRule.getEventParameters()));
+                
+                currentEvent = new MFCEvent(currentType, currentTarget, windowTree.getGUIModel());
+                
+                for (EventGenerationRule.ReplayMessageSpec replayMessageSpec :
+                      currentRule.getReplayMessageSpecifications())
+                {
+                    if (replayMessageSpec.generateSingleMessage()) {
+                        try {
+                            generateReplayMessage(replayMessageSpec);
+                        }
+                        catch (InvalidParameterException e) {
+                            Console.printerrln(e.getMessage());
+                            // TODO currentToken.invalidateReplay();
+                        }
+                    }
+                    else {
+                        try {
+                            generateReplaySequence(replayMessageSpec);
+                            // TODO currentToken.invalidateReplay();
+                        }
+                        catch (InvalidParameterException e) {
+                            Console.printerrln(e.getMessage());
+                            // TODO currentToken.invalidateReplay();
+                        }
+                    }
+                }
+
+                Console.traceln(currentEvent.getType().toString() + " matched");
+            }
+            else {
+                currentEvent = null;
+            }
+        }
+        if (!isMatch) {
+            Console.traceln("no match found for sequence: " + sequence.toString());
+        }
+        
+        
+        /*if (currentEvent != null && currentEvent.getReplayables() != null) {
+            System.out.println("replay messages are ");
+            for (de.ugoe.cs.quest.eventcore.IReplayable msg : currentEvent.getReplayables()) {
+                System.out.println("    " + msg + "  " + msg.getReplay());
+            }
+        }
+
+        System.out.println();*/
+
+
+        return currentEvent;
+    }
+
+    // ////////////////////////////////////////////////////////////
+    // Helper functions for matching of events, i.e., msg-nodes //
+    // ////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param currentRule
+     */
+    private boolean evaluateMessageConditions(EventGenerationRule currentRule) {
+        boolean isMatch = true;
+        List<EventGenerationRule.MessageCondition> messageConditions =
+            currentRule.getMessageConditions();
+
+        int i = 0;
+        while (isMatch && i < messageConditions.size()) {
+            EventGenerationRule.MessageCondition messageCondition = messageConditions.get(i);
+            if (messageCondition.matchMultiple()) {
+                EventGenerationRule.MessageCondition nextMessageCondition = null;
+                if (i + 1 < messageConditions.size()) {
+                    nextMessageCondition = messageConditions.get(i + 1);
+                }
+                try {
+                    isMatch = matchMultipleConditions(messageCondition, nextMessageCondition);
+                }
+                catch (InvalidParameterException e) {
+                    Console.printerrln(e.getMessage());
+                }
+            }
+            else {
+                try {
+                    isMatch = matchSingleMessage(messageCondition);
+                }
+                catch (InvalidParameterException e) {
+                    Console.printerrln(e.getMessage());
+                }
+            }
+            i++;
+        }
+        
+        return isMatch;
+    }
+
+    /**
+     * <p>
+     * Handles msg-nodes where multiple is not true, i.e., not a sequences.
+     * </p>
+     * 
+     * @param messageElement
+     *            {@link Element} representing the msg-node
+     * @return true, if a match is found; false otherwise
+     */
+    private boolean matchSingleMessage(EventGenerationRule.MessageCondition condition) {
+        boolean isMatch = false;
+        WindowsMessage currentMessage = null;
+
+        WindowsMessageType type = condition.getMessageType();
+
+        while (!isMatch && sequenceIterator.hasNext()) {
+            /*
+             * traverses the messages from the current position forward till a message with the
+             * correct type is found
+             */
+            currentMessage = sequenceIterator.next();
+            if (type == currentMessage.getType()) {
+                // message with the correct type found
+                // eval child nodes for further matching/storing
+                isMatch = evaluateMessageCondition(currentMessage, condition);
+
+                // in case the message is a match, eval storage children
+                if (isMatch) {
+                    handleStorage(condition, currentMessage);
+                    currentTarget = currentMessage.getTarget();
+                    // TODO currentToken.setTargetShort(currentMessage.getParentNames());
+                }
+            }
+        }
+
+        return isMatch;
+    }
+
+    /**
+     * <p>
+     * Handles msg-nodes where multiple is true, i.e., sequences. Requires knowledge about the next
+     * msg-node to determine the end of the sequence.
+     * </p>
+     * 
+     * @param messageElement
+     *            {@link Element} representing the msg-node
+     * @param nextMessageElement
+     *            {@link Element} representing the next msg-node; {@code null} if the current node
+     *            is the last one
+     * @return true, if a sequence is matched; false otherwise
+     */
+    private boolean matchMultipleConditions(EventGenerationRule.MessageCondition condition,
+                                            EventGenerationRule.MessageCondition nextCondition)
+    {
+        boolean isMatch = false;
+        boolean isCurrentMatch = false;
+        boolean nextMatchFound = false;
+        WindowsMessage currentMessage = null;
+        WindowsMessage nextMessage = null;
+
+        WindowsMessageType type = condition.getMessageType();
+
+        WindowsMessageType nextType = null;
+        if (nextCondition != null) {
+            nextType = nextCondition.getMessageType();
+        }
+
+        while (!nextMatchFound && sequenceIterator.hasNext()) {
+            currentMessage = sequenceIterator.next();
+            if (type == currentMessage.getType()) {
+                isCurrentMatch = evaluateMessageCondition(currentMessage, condition);
+                isMatch = isMatch || isCurrentMatch;
+
+                if (isCurrentMatch) {
+                    handleStorage(condition, currentMessage);
+                    currentTarget = currentMessage.getTarget();
+                    // TODO currentToken.setTargetShort(currentMessage.getParentNames());
+                }
+            }
+            if (nextCondition != null && isMatch) {
+                // peek next message to check if the sequence ends and the next
+                // match is found
+                if (!sequenceIterator.hasNext()) {
+                    return false; // sequence is over, but not all messages are
+                                  // found
+                }
+                nextMessage = sequenceIterator.next();
+                sequenceIterator.previous();
+
+                if (nextType == nextMessage.getType()) {
+                    nextMatchFound = evaluateMessageCondition(nextMessage, nextCondition);
+                }
+
+            }
+        }
+
+        return isMatch;
+    }
+
+    /**
+     * <p>
+     * Handles equals-nodes.
+     * </p>
+     * 
+     * @param currentMessage
+     *            {@link Element} representing the msg-node the equals-node belongs to
+     * @param messageElement
+     *            {@link Element} representing the equals-node to be evaluated
+     * @return true, if constraint is fulfilled; false otherwise
+     */
+    private boolean evaluateMessageCondition(WindowsMessage                       currentMessage,
+                                             EventGenerationRule.MessageCondition condition)
+    {
+        boolean isMatch = true;
+        for (int i = 0; isMatch && (i < condition.getAttributeConditions().size()); i++)
+        {
+            EventGenerationRule.AttributeCondition attrCond =
+                condition.getAttributeConditions().get(i);
+            
+            // the size 2 of termElements is guaranteed by the XML schema
+            Object value1 = getTermValue(currentMessage, attrCond.getLeftHandSide(), Object.class);
+            Object value2 = getTermValue(currentMessage, attrCond.getRightHandSide(), Object.class);
+            if (value1 == null || value2 == null) {
+                isMatch = false;
+            }
+            else {
+                isMatch = isMatch && value1.equals(value2);
+            }
+        }
+//        for (Element childElement : (List<Element>) messageElement.getChildren("equalsSeq",
+//                                                                               rulesNamespace))
+//        {
+//            List<Element> termElements = childElement.getChildren();
+//            List<String> values1 = getTermValueSeq(termElements.get(0));
+//            List<String> values2 = getTermValueSeq(termElements.get(0));
+//            if (values1 == null || values2 == null) {
+//                isMatch = false;
+//            }
+//            else {
+//                isMatch = isMatch && values1.equals(values2);
+//            }
+//        }
+        return isMatch;
+    }
+
+    /**
+     * <p>
+     * Handles store-nodes and storeSeq-nodes.
+     * </p>
+     * 
+     * @param messageElement
+     *            {@link Element} representing the msg-node that is currently being evaluated
+     * @param currentMessage
+     *            current message in the message sequence that is matched; this is the message that
+     *            is stored
+     */
+    @SuppressWarnings("unchecked")
+    private void handleStorage(EventGenerationRule.MessageCondition messageCondition,
+                               WindowsMessage                       currentMessage)
+    {
+        for (Term valueToStore : messageCondition.getMessagesToStore())
+        {
+            if (valueToStore.getMessageId() != null) {
+              ReplayWindowsMessage replayMessage = new ReplayWindowsMessage(currentMessage);
+              messageStorage.put(valueToStore.getMessageId(), replayMessage);
+              resolveHwnd(replayMessage, valueToStore.getResolveHandles());
+            }
+            else if (valueToStore.getSequenceId() != null) {
+                Object tmp = messageStorage.get(valueToStore.getSequenceId());
+                ReplayWindowsMessage replayMessage = new ReplayWindowsMessage(currentMessage);
+                List<ReplayWindowsMessage> storedSequence;
+                if (tmp == null || tmp instanceof ReplayWindowsMessage) {
+                    storedSequence = new LinkedList<ReplayWindowsMessage>();
+                    storedSequence.add(replayMessage);
+                    messageStorage.put(valueToStore.getSequenceId(), storedSequence);
+                }
+                else if (tmp instanceof List<?>) {
+                    storedSequence = (List<ReplayWindowsMessage>) tmp;
+                    storedSequence.add(replayMessage);
+                    messageStorage.put(valueToStore.getSequenceId(), storedSequence);
+                }
+                resolveHwnd(replayMessage, valueToStore.getResolveHandles());
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Resolves a parameter that contains a HWND of a message to the target string of the HWND and
+     * stores it.
+     * </p>
+     * 
+     * @param currentMessage
+     *            message whose HWND is resolved
+     * @param list
+     *            child element of the store node that represents the resolve
+     */
+    private void resolveHwnd(ReplayWindowsMessage currentMessage, List<Term> resolveHandles) {
+        if (resolveHandles != null) {
+            for (Term resolveElement : resolveHandles) {
+                String param = resolveElement.getMessageParameterName();
+                String storeParam = resolveElement.getStoreParameterName();
+                long paramHwnd = (Long) currentMessage.getParameter(param);
+                MFCGUIElement guiElement = windowTree.find(paramHwnd);
+                if (guiElement != null) {
+                    currentMessage.addParameter(storeParam, "" + guiElement.toXML());
+                }
+            }
+        }
+    }
+
+    // /////////////////////////////////////////////////////
+    // Helper functions for generating the replay, i.e.,
+    // parsing of genMsg und genMsgSeq-nodes
+    // /////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * Handles genMsg-nodes and adds the replay to the {@link Event} that is generated.
+     * </p>
+     * 
+     * @param genMsgElement
+     *            {@link Element} representing the genMsg-node
+     */
+    private void generateReplayMessage(EventGenerationRule.ReplayMessageSpec messageSpec) {
+        ReplayWindowsMessage generatedMessage = null;
+        if (messageSpec.getReplayObjectId() != null) { // replay stored message without change
+            generatedMessage = getStoredMessageVariable(null, messageSpec.getReplayObjectId());
+        }
+        else { // generate message according to the rule
+            generatedMessage = new ReplayWindowsMessage
+                (getTermValue(messageSpec.getType(), WindowsMessageType.class));
+            generatedMessage.setTargetXML(getTermValue(messageSpec.getTarget(), String.class));
+
+            if ((messageSpec.getLparamHiWord() != null) ||
+                    (messageSpec.getLparamLoWord() != null))
+            {
+                generatedMessage.setLPARAM
+                    (loHiWord(messageSpec.getLparamLoWord(), messageSpec.getLparamHiWord()));
+            }
+            else if (messageSpec.getLparam() != null) {
+                try {
+                    generatedMessage.setLPARAM(getTermValue(messageSpec.getLparam(), Long.class));
+                }
+                catch (IllegalArgumentException e) {
+                    generatedMessage.setLPARAMasWindowDesc
+                        (getTermValue(messageSpec.getLparam(), String.class));
+                }
+            }
+
+            if ((messageSpec.getWparamHiWord() != null) ||
+                    (messageSpec.getWparamLoWord() != null))
+            {
+                generatedMessage.setWPARAM
+                    (loHiWord(messageSpec.getWparamLoWord(), messageSpec.getWparamHiWord()));
+            }
+            else if (messageSpec.getWparam() != null) {
+                try {
+                    generatedMessage.setWPARAM(getTermValue(messageSpec.getWparam(), Long.class));
+                }
+                catch (IllegalArgumentException e) {
+                    generatedMessage.setWPARAMasWindowDesc
+                        (getTermValue(messageSpec.getWparam(), String.class));
+                }
+            }
+            
+            
+        }
+
+        generatedMessage.setDelay(messageSpec.getDelay());
+
+        currentEvent.addReplayable(generatedMessage);
+    }
+
+    /**
+     * Handles genMsgSeq-nodes and adds the replay to the {@link Event} that is generated.</p>
+     * 
+     * @param genMsgElement
+     *            {@link Element} representing the genMsgSeq-node.
+     */
+    private void generateReplaySequence(EventGenerationRule.ReplayMessageSpec messageSpec)
+    {
+        List<ReplayWindowsMessage> generatedMessageSeq = new LinkedList<ReplayWindowsMessage>();
+        if (messageSpec.getReplayObjectId() != null) { // replay stored sequence without changes
+            generatedMessageSeq = getStoredSeqVariable(messageSpec.getReplayObjectId());
+        }
+        else {
+            List<ReplayWindowsMessage> seqVar =
+                getStoredSeqVariable(messageSpec.getReplayObjectId());
+            
+            Term typeTerm = messageSpec.getType();
+            if (typeTerm.getSequenceId() != null) {
+                seqVar = getStoredSeqVariable(typeTerm.getSequenceId());
+                for (WindowsMessage msg : seqVar) {
+                    ReplayWindowsMessage replayMessage = new ReplayWindowsMessage(msg.getType());
+                    replayMessage.setDelay(messageSpec.getDelay());
+                    generatedMessageSeq.add(replayMessage);
+                }
+            }
+            else { // constValue type
+                WindowsMessageType constMsgType = getTermValue(typeTerm, WindowsMessageType.class);
+                for (int i = 0; i < seqVar.size(); i++) {
+                    ReplayWindowsMessage replayMessage = new ReplayWindowsMessage(constMsgType);
+                    replayMessage.setDelay(messageSpec.getDelay());
+                    generatedMessageSeq.add(replayMessage);
+                }
+            }
+
+            createSequenceTarget(generatedMessageSeq, messageSpec);
+            createSequenceLParam(generatedMessageSeq, messageSpec);
+            createSequenceWParam(generatedMessageSeq, messageSpec);
+        }
+        
+        currentEvent.addReplayableSequence(generatedMessageSeq);
+    }
+
+    /**
+     * <p>
+     * Creates the targets for replay sequences generated with genMsgSeq-nodes.
+     * </p>
+     * 
+     * @param generatedMessageSeq
+     *            list of the messages that is being generated
+     * @param msgsGenerated
+     *            boolean stating if the list of messages is already generated or if the generation
+     *            has to be handles by this method
+     * @param constMsgType
+     *            a constant message type that is used for message generation, in case the list of
+     *            message is generated by this method
+     * @param termElement
+     *            {@link Element} representing the term-node describing the target
+     * @return true, if the list of message is generated after calling this method; false otherwise
+     * @throws NoSuchElementException
+     *             thrown if the seqVar referred to in the termElement contains a different number
+     *             of messages than is contained in messageSeq
+     */
+    private void createSequenceTarget(List<ReplayWindowsMessage>            generatedMessageSeq,
+                                      EventGenerationRule.ReplayMessageSpec messageSpec)
+        throws NoSuchElementException
+    {
+        Iterator<ReplayWindowsMessage> seqIterator = generatedMessageSeq.iterator();
+        if (messageSpec.getTarget().getSequenceId() != null) {
+            List<ReplayWindowsMessage> seqVar =
+                getStoredSeqVariable(messageSpec.getTarget().getSequenceId());
+
+            if (seqVar.size() != generatedMessageSeq.size()) {
+                throw new InvalidParameterException
+                    ("Failure generating replay sequence for rule " + currentRuleName +
+                     ": One or more of the sequence variables used to generate a sequence have " +
+                     "different lenghts.");
+            }
+            
+            for (WindowsMessage msg : seqVar) {
+                seqIterator.next().setTarget(msg.getTarget());
+            }
+        }
+        else { // const value
+            throw new AssertionError("target must be a sequence variable!");
+            /*
+             * If target would not be a variable, the message-elements could not yet be created and
+             * the whole sequence might be broken. If this is to be changed, createSequenceLParam
+             * and createSequenceWParam need to be addepted, too.
+             */
+        }
+    }
+
+    /**
+     * <p>
+     * Creates the LPARAMs for replay sequences generated with genMsgSeq-nodes.
+     * </p>
+     * 
+     * @param generatedMessageSeq
+     *            list of the messages that is being generated
+     * @param msgsGenerated
+     *            boolean stating if the list of messages is already generated or if the generation
+     *            has to be handles by this method
+     * @param constMsgType
+     *            a constant message type that is used for message generation, in case the list of
+     *            message is generated by this method
+     * @param termElement
+     *            {@link Element} representing the term-node describing the LPARAM
+     * @return true, if the list of message is generated after calling this method; false otherwise
+     * @throws NoSuchElementException
+     *             thrown if the seqVar referred to in the termElement contains a different number
+     *             of messages than is contained in messageSeq
+     */
+    private void createSequenceLParam(List<ReplayWindowsMessage>            generatedMessageSeq,
+                                      EventGenerationRule.ReplayMessageSpec messageSpec)
+        throws NoSuchElementException
+    {
+        Iterator<ReplayWindowsMessage> seqIterator = generatedMessageSeq.iterator();
+        if (messageSpec.getLparam().getSequenceId() != null) {
+            List<ReplayWindowsMessage> seqVar =
+                getStoredSeqVariable(messageSpec.getLparam().getSequenceId());
+            
+            if (seqVar.size() != generatedMessageSeq.size()) {
+                throw new InvalidParameterException
+                    ("Failure generating replay sequence for rule " + currentRuleName +
+                     ": One or more of the sequence variables used to generate a sequence have " +
+                     "different lengths.");
+            }
+            for (WindowsMessage msg : seqVar) {
+                ReplayWindowsMessage currentSeqMsg = seqIterator.next();
+                Object paramValue =
+                    msg.getParameter(messageSpec.getLparam().getSequenceParameterName());
+                if (paramValue instanceof Long) {
+                    currentSeqMsg.setLPARAM((Long) paramValue);
+                }
+                else {
+                    currentSeqMsg.setLPARAMasWindowDesc((String) paramValue);
+                }
+            }
+        }
+        else { // const value
+            int paramValue = getTermValue(messageSpec.getLparam(), int.class);
+            while (seqIterator.hasNext()) {
+                seqIterator.next().setLPARAM(paramValue);
+            }
+        }
+
+    }
+
+    /**
+     * <p>
+     * Creates the WPARAMs for replay sequences generated with genMsgSeq-nodes.
+     * </p>
+     * 
+     * @param generatedMessageSeq
+     *            list of the messages that is being generated
+     * @param msgsGenerated
+     *            boolean stating if the list of messages is already generated or if the generation
+     *            has to be handles by this method
+     * @param constMsgType
+     *            a constant message type that is used for message generation, in case the list of
+     *            message is generated by this method
+     * @param termElement
+     *            {@link Element} representing the term-node describing the WPARAM
+     * @return true, if the list of message is generated after calling this method; false otherwise
+     * @throws NoSuchElementException
+     *             thrown if the seqVar referred to in the termElement contains a different number
+     *             of messages than is contained in messageSeq
+     */
+    private void createSequenceWParam(List<ReplayWindowsMessage>            generatedMessageSeq,
+                                      EventGenerationRule.ReplayMessageSpec messageSpec)
+        throws NoSuchElementException
+    {
+        Iterator<ReplayWindowsMessage> seqIterator = generatedMessageSeq.iterator();
+        if (messageSpec.getWparam().getSequenceId() != null) {
+            List<ReplayWindowsMessage> seqVar =
+                getStoredSeqVariable(messageSpec.getWparam().getSequenceId());
+            
+            if (seqVar.size() != generatedMessageSeq.size()) {
+                throw new InvalidParameterException
+                    ("Failure generating replay sequence for rule " + currentRuleName +
+                     ": One or more of the sequence variables used to generate a sequence have " +
+                     "different lengths.");
+            }
+            for (WindowsMessage msg : seqVar) {
+                ReplayWindowsMessage currentSeqMsg = seqIterator.next();
+                Object paramValue =
+                    msg.getParameter(messageSpec.getWparam().getSequenceParameterName());
+                if (paramValue instanceof Long) {
+                    currentSeqMsg.setWPARAM((Long) paramValue);
+                }
+                else {
+                    currentSeqMsg.setWPARAMasWindowDesc((String) paramValue);
+                }
+            }
+        }
+        else { // const value
+            int paramValue = getTermValue(messageSpec.getWparam(), int.class);
+            while (seqIterator.hasNext()) {
+                seqIterator.next().setWPARAM(paramValue);
+            }
+        }
+    }
+
+    // ////////////////////////////
+    // General helper functions //
+    // ////////////////////////////
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param eventParameters
+     * @return
+     */
+    private Map<String, String> resolveParameters(List<Term> eventParameters) {
+        Map<String, String> resultParameters = null;
+        
+        if ((eventParameters != null) && (eventParameters.size() > 0)) {
+            resultParameters = new HashMap<String, String>();
+            
+            for (Term term : eventParameters) {
+                if ("seqValue".equals(term.getName())) {
+                    List<String> values = getTermValueAsList(term, String.class);
+                                        
+                    resultParameters.put
+                        (term.getSequenceParameterName(), (String) values.get(values.size() - 1));
+                }
+                else {
+                    resultParameters.put
+                        (term.getMessageParameterName(), getTermValue(term, String.class));
+                }
+            }
+        }
+        
+        return resultParameters;
+    }
+
+    /**
+     * <p>
+     * Retrieves a message from the storage for, e.g., comparison or replay. "this" is used to refer
+     * to the current message.
+     * </p>
+     * 
+     * @param currentMessage
+     *            current message during the parsing; passed to handle "this"
+     * @param obj
+     *            object identifier in the storage
+     * @return message retrieved from the storage
+     * @throws InvalidParameterException
+     *             thrown in case of invalid uses of "this" or if no message with the identifier obj
+     *             is found in the storage
+     */
+    private ReplayWindowsMessage getStoredMessageVariable(WindowsMessage currentMessage, String obj)
+        throws InvalidParameterException
+    {
+        ReplayWindowsMessage varMessage = null;
+        if (obj.equals("this")) {
+            if (currentMessage == null) {
+                throw new InvalidParameterException("Failure obtaining term value for rule " +
+                    currentRuleName +
+                    ": \"this\" is not a valid name for generating runtime messages.");
+            }
+            varMessage = new ReplayWindowsMessage(currentMessage);
+        }
+        else {
+            Object tmp = messageStorage.get(obj);
+            if (tmp instanceof ReplayWindowsMessage) {
+                varMessage = (ReplayWindowsMessage) tmp;
+            }
+            else {
+                throw new InvalidParameterException("Failure obtaining term value for rule " +
+                    currentRuleName + ": No message \"" + obj + "\" stored.");
+            }
+        }
+        return varMessage;
+    }
+
+    /**
+     * <p>
+     * Retrieves a stored message sequence from the storage.
+     * </p>
+     * 
+     * @param obj
+     *            object identifier in the storage
+     * @return message sequence retrieved from the storage
+     * @throws IllegalArgumentException
+     *             thrown if no message sequences with the identifier obj is found in the storage
+     */
+    @SuppressWarnings("unchecked")
+    private List<ReplayWindowsMessage> getStoredSeqVariable(String obj)
+        throws IllegalArgumentException
+    {
+        List<ReplayWindowsMessage> varMsgSeq = null;
+        Object tmp = messageStorage.get(obj);
+        if (tmp instanceof List<?>) {
+            varMsgSeq = (List<ReplayWindowsMessage>) tmp;
+        }
+        else {
+            throw new IllegalArgumentException("Failure obtaining term value for rule " +
+                                               currentRuleName + ": No sequence \"" + obj +
+                                               "\" store.");
+        }
+        return varMsgSeq;
+    }
+
+    /**
+     * <p>
+     * convenience method for {@link #getTermValue(WindowsMessage, Term)} with current message is
+     * null.
+     * </p>
+     * 
+     * @param termElement
+     *            {@link Element} representing the term node
+     * @return value of the term or {@code null} of the term node could not be evaluated
+     */
+    private <T> T getTermValue(EventGenerationRule.Term term, Class<T> expectedType) {
+        return getTermValue(null, term, expectedType);
+    }
+
+    /**
+     * <p>
+     * Handles term-nodes and returns the value of the described term.
+     * </p>
+     * 
+     * @param currentMessage
+     *            current message during the parsing; required to resolve references to "this" in a
+     *            term
+     * @param termElement
+     *            {@link Element} representing the term node
+     * @return value of the term or {@code null} of the term node could not be evaluated
+     */
+    private <T> T getTermValue(WindowsMessage           currentMessage,
+                               EventGenerationRule.Term term,
+                               Class<T>                 expectedType)
+    {
+        T value = null;
+        
+        if ("constValue".equals(term.getName())) {
+            value = getValueAsType(term.getValue(), expectedType);
+        }
+        else if ("paramValue".equals(term.getName())) {
+            String objectName = term.getMessageId();
+            WindowsMessage varMessage = getStoredMessageVariable(currentMessage, objectName);
+            if (varMessage != null) {
+                String param = term.getMessageParameterName();
+                value = getValueAsType(varMessage.getParameter(param), expectedType);
+            }
+        }
+        else if ("winInfoValue".equals(term.getName())) {
+            String objectName = term.getMessageId();
+            WindowsMessage varMessage = getStoredMessageVariable(currentMessage, objectName);
+            if (varMessage != null) {
+                String paramString = term.getWindowParameterName();
+                if (paramString.equals("class")) {
+                    value = getValueAsType
+                        (((MFCGUIElement) varMessage.getTarget()).getType(), expectedType);
+                }
+                else if (paramString.equals("resourceId")) {
+                    value = getValueAsType
+                        (((MFCGUIElement) varMessage.getTarget()).getResourceId(), expectedType);
+                }
+                else if (paramString.equals("hwnd")) {
+                    value = getValueAsType
+                        (((MFCGUIElement) varMessage.getTarget()).getId(), expectedType);
+                }
+                else if (paramString.equals("parentTarget")) {
+                    String target = varMessage.getTargetXML();
+                    int index = target.lastIndexOf("<");
+                    if (index == 0) {
+                        Console.traceln("Trying to adress parent of top-level window! Replay " +
+                        		"probably invalid!");
+                    }
+                    value =  getValueAsType(target.substring(0, index), expectedType);
+                }
+                else if (paramString.equals("parentClass")) {
+                    value =  getValueAsType
+                        (((MFCGUIElement) varMessage.getTarget())
+                        .getParent().getSpecification().getType(), expectedType);
+                }
+            }
+        }
+        else if ("msgInfoValue".equals(term.getName())) {
+            String objectName = term.getMessageId();
+            WindowsMessage varMessage = getStoredMessageVariable(currentMessage, objectName);
+            if (varMessage != null) {
+                String paramString = term.getMessageInfoName();
+                if (paramString.equals("type")) {
+                    value = getValueAsType(varMessage.getType(), expectedType);
+                }
+                else if (paramString.equals("target")) {
+                    value = getValueAsType(varMessage.getTargetXML(), expectedType);
+                }
+            }
+        }
+        else if ("msgInfoValue".equals(term.getName())) {
+            String objectName = term.getMessageId();
+            WindowsMessage varMessage = getStoredMessageVariable(currentMessage, objectName);
+            if (varMessage != null) {
+                String paramString = term.getMessageInfoName();
+                if (paramString.equals("type")) {
+                    value = getValueAsType(varMessage.getType(), expectedType);
+                }
+                else if (paramString.equals("target")) {
+                    value = getValueAsType(varMessage.getTargetXML(), expectedType);
+                }
+            }
+        }
+        
+        return value;
+    }
+    
+    /**
+     * <p>
+     * convenience method for {@link #getTermValueAsList(WindowsMessage, Term)} with current
+     * message is null.
+     * </p>
+     * 
+     * @param termElement
+     *            {@link Element} representing the term node
+     * @return value of the term or {@code null} of the term node could not be evaluated
+     */
+    private <T> List<T> getTermValueAsList(EventGenerationRule.Term term, Class<T> expectedType) {
+        return getTermValueAsList(null, term, expectedType);
+    }
+
+    /**
+     * <p>
+     * Handles term-nodes and returns the value of the described term.
+     * </p>
+     * 
+     * @param currentMessage
+     *            current message during the parsing; required to resolve references to "this" in a
+     *            term
+     * @param termElement
+     *            {@link Element} representing the term node
+     * @return value of the term or {@code null} of the term node could not be evaluated
+     */
+    private <T> List<T> getTermValueAsList(WindowsMessage           currentMessage,
+                                           EventGenerationRule.Term term,
+                                           Class<T>                 expectedElementType)
+    {
+        List<T> values = new ArrayList<T>();
+        if ("seqValue".equals(term.getName())) {
+            List<ReplayWindowsMessage> seqVar = getStoredSeqVariable(term.getSequenceId());
+            Object value;
+            
+            for (ReplayWindowsMessage msg : seqVar) {
+                // msg.getParameter returns null, if parameter is not found,
+                // therefore the List can contain null-values
+                value = msg.getParameter(term.getSequenceParameterName());
+                values.add(getValueAsType(value, expectedElementType));
+            }
+        }
+        else {
+            values.add(getTermValue(currentMessage, term, expectedElementType));
+        }
+        
+        return values;
+    }
+    
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param value
+     * @param expectedType
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    private <T> T getValueAsType(Object value, Class<T> expectedType) {
+        if (expectedType.isInstance(value)) {
+            return (T) value;
+        }
+        else if (value instanceof String) {
+            try {
+                if (WindowsMessageType.class.equals(expectedType)) {
+                    return (T) WindowsMessageType.parseMessageType((String) value);
+                }
+                else if (Short.class.equals(expectedType)) {
+                    return (T) (Short) Short.parseShort((String) value);
+                }
+            }
+            catch (Exception e) {
+                // in this case, the value can not be transformed to the expected value. So ignore
+                // the exception and fall through to the exception thrown anyway
+            }
+        }
+        else if (value instanceof Long) {
+            try {
+                if (Short.class.equals(expectedType)) {
+                    return (T) (Short) ((Long) value).shortValue();
+                }
+                else if (String.class.equals(expectedType)) {
+                    return (T) ((Long) value).toString();
+                }
+            }
+            catch (Exception e) {
+                // in this case, the value can not be transformed to the expected value. So ignore
+                // the exception and fall through to the exception thrown anyway
+            }
+        }
+        
+        throw new IllegalArgumentException("the term value is not of the expected type " +
+                                           expectedType + " but a " +
+                                           (value != null ? value.getClass() : "null"));
+    }
+
+    /**
+     * <p>
+     * Handles LOWORD and HIWORD child nodes of LPARAM and WPARAM nodes. The returned value is the
+     * LPARAM/WPARAM value based on the LOWORD and HIWORD.
+     * </p>
+     * 
+     * @param param
+     *            {@link Element} representing the LPARAM/WPARAM node
+     * @return value of the LPARAM/WPARAM
+     */
+    private long loHiWord(EventGenerationRule.Term lword, EventGenerationRule.Term hword) {
+        return MAKEPARAM(getTermValue(lword, Short.class), getTermValue(hword, Short.class));
+    }
+
+    /**
+     * <p>
+     * Takes to short integers and combines them into the high and low order bits of an integer.
+     * </p>
+     * 
+     * @param loword
+     *            low word
+     * @param hiword
+     *            high word
+     * @return combined integer
+     */
+    private static int MAKEPARAM(short loword, short hiword) {
+        return loword | ((int) hiword) << Short.SIZE;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     */
+    @SuppressWarnings("unchecked")
+    private void parseGenerationRules() {
+        SAXBuilder builder = new SAXBuilder();
+        Document doc = null;
+
+        try {
+            doc = builder.build(rulesFile);
+            rulesNamespace = Namespace.getNamespace("ul:rules");
+        }
+        catch (JDOMException e) {
+            Console.printerrln("Invalid rules file.");
+            e.printStackTrace();
+        }
+        catch (IOException e) {
+            Console.printerrln("Invalid rules file.");
+            e.printStackTrace();
+        }
+
+        Element rulesRoot = doc.getRootElement();
+        
+        List<Element> ruleElements = rulesRoot.getChildren("rule", rulesNamespace);
+
+        generationRules = new ArrayList<EventGenerationRule>();
+
+        for (Element ruleElement : ruleElements) {
+            generationRules.add(new EventGenerationRule(ruleElement, rulesNamespace));
+        }
+    }
 
 }
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/HandlerCreate.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/HandlerCreate.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/HandlerCreate.java	(revision 619)
@@ -1,10 +1,10 @@
+
 package de.ugoe.cs.quest.plugin.mfc;
 
-import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowTree;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.WindowTree;
 
 /**
  * <p>
- * Message handler for {@code WM_CREATE} messages. The handler maintains the
- * {@link WindowTree}.
+ * Message handler for {@code WM_CREATE} messages. The handler maintains the {@link WindowTree}.
  * </p>
  * 
@@ -14,112 +14,119 @@
 public class HandlerCreate extends MessageHandler {
 
-	/**
-	 * <p>
-	 * Constructor. Creates a new HandlerCreate.
-	 * </p>
-	 */
-	public HandlerCreate() {
-		super();
-	}
+    /**
+     * <p>
+     * Constructor. Creates a new HandlerCreate.
+     * </p>
+     * 
+     * @param windowTree the tree of GUI element specifications to be created and adapted during
+     *                   parsing
+     */
+    public HandlerCreate(WindowTree windowTree) {
+        super(windowTree);
+    }
 
-	/**
-	 * <p>
-	 * Name of the created window.
-	 * </p>
-	 */
-	private String windowName;
+    /**
+     * <p>
+     * Name of the created window.
+     * </p>
+     */
+    private String windowName;
 
-	/**
-	 * <p>
-	 * HWND of the created window.
-	 * </p>
-	 */
-	private int hwnd;
+    /**
+     * <p>
+     * HWND of the created window.
+     * </p>
+     */
+    private long hwnd;
 
-	/**
-	 * <p>
-	 * HWND of the created window's parent.
-	 * </p>
-	 */
-	private int parentHwnd;
+    /**
+     * <p>
+     * HWND of the created window's parent.
+     * </p>
+     */
+    private long parentHwnd;
 
-	/**
-	 * <p>
-	 * Resource Id of the created window.
-	 * </p>
-	 */
-	private int resourceId;
+    /**
+     * <p>
+     * Resource Id of the created window.
+     * </p>
+     */
+    private int resourceId;
 
-	/**
-	 * <p>
-	 * Window class of the created window.
-	 * </p>
-	 */
-	private String className;
+    /**
+     * <p>
+     * Window class of the created window.
+     * </p>
+     */
+    private String className;
 
-	/**
-	 * <p>
-	 * Modality of the created window.
-	 * </p>
-	 */
-	private boolean isModal;
+    /**
+     * <p>
+     * Modality of the created window.
+     * </p>
+     */
+    private boolean isModal;
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onEndElement()
-	 */
-	@Override
-	public void onEndElement() {
-		if (hwnd != 0) {
-			WindowTree.getInstance().add(parentHwnd, hwnd, windowName,
-					resourceId, className, isModal);
-		}
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onEndElement()
+     */
+    @Override
+    public void onEndElement() {
+        if (hwnd != 0) {
+            super.getWindowTree().add(parentHwnd, hwnd, windowName, resourceId, className, isModal);
+        }
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * de.ugoe.cs.quest.plugin.mfc.MessageHandler#onParameter(java.lang.String
-	 * , java.lang.String)
-	 */
-	@Override
-	public void onParameter(String name, String value) {
-		if (name.equals("window.hwnd")) {
-			hwnd = Integer.parseInt(value);
-		} else if (name.equals("window.name")) {
-			windowName = value;
-		} else if (name.equals("window.parent.hwnd")) {
-			parentHwnd = Integer.parseInt(value);
-		} else if (name.equals("window.resourceId")) {
-			resourceId = Integer.parseInt(value);
-		} else if (name.equals("window.class")) {
-			if (value.startsWith("Afx:")) {
-				className = "Afx:";
-			} else {
-				className = value;
-			}
-		} else if (name.equals("window.ismodal")) {
-			if (value.equals("true") || value.equals("1")) {
-				isModal = true;
-			}
-		}
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onParameter(java.lang.String ,
+     * java.lang.String)
+     */
+    @Override
+    public void onParameter(String name, String value) {
+        if (name.equals("window.hwnd")) {
+            hwnd = Long.parseLong(value);
+        }
+        else if (name.equals("window.name")) {
+            windowName = value;
+        }
+        else if (name.equals("window.parent.hwnd")) {
+            parentHwnd = Long.parseLong(value);
+        }
+        else if (name.equals("window.resourceId")) {
+            resourceId = Integer.parseInt(value);
+        }
+        else if (name.equals("window.class")) {
+            if (value.startsWith("Afx:")) {
+                className = "Afx:";
+            }
+            else {
+                className = value;
+            }
+        }
+        else if (name.equals("window.ismodal")) {
+            if (value.equals("true") || value.equals("1")) {
+                isModal = true;
+            }
+        }
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onStartElement()
-	 */
-	@Override
-	public void onStartElement() {
-		windowName = "";
-		hwnd = 0;
-		parentHwnd = 0;
-		resourceId = 0;
-		className = "";
-		isModal = false;
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onStartElement()
+     */
+    @Override
+    public void onStartElement() {
+        windowName = "";
+        hwnd = 0;
+        parentHwnd = 0;
+        resourceId = 0;
+        className = "";
+        isModal = false;
+    }
 
 }
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/HandlerDestroy.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/HandlerDestroy.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/HandlerDestroy.java	(revision 619)
@@ -1,10 +1,10 @@
+
 package de.ugoe.cs.quest.plugin.mfc;
 
-import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowTree;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.WindowTree;
 
 /**
  * <p>
- * Handler for {@code WM_DESTROY} message. The handler maintains the
- * {@link WindowTree}.
+ * Handler for {@code WM_DESTROY} message. The handler maintains the {@link WindowTree}.
  * </p>
  * 
@@ -14,55 +14,57 @@
 public class HandlerDestroy extends MessageHandler {
 
-	/**
-	 * <p>
-	 * Constructor. Creates a new HandlerDestroy.
-	 * </p>
-	 */
-	public HandlerDestroy() {
-		super();
-	}
+    /**
+     * <p>
+     * Constructor. Creates a new HandlerDestroy.
+     * </p>
+     * 
+     * @param windowTree
+     *            the tree of GUI element specifications to be created and adapted during parsing
+     */
+    public HandlerDestroy(WindowTree windowTree) {
+        super(windowTree);
+    }
 
-	/**
-	 * <p>
-	 * HWND of the window that is destroyed.
-	 * </p>
-	 */
-	private int hwnd;
+    /**
+     * <p>
+     * HWND of the window that is destroyed.
+     * </p>
+     */
+    private long hwnd;
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onEndElement()
-	 */
-	@Override
-	public void onEndElement() {
-		if (hwnd != 0) {
-			WindowTree.getInstance().remove(hwnd);
-		}
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onEndElement()
+     */
+    @Override
+    public void onEndElement() {
+        if (hwnd != 0) {
+            super.getWindowTree().remove(hwnd);
+        }
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * de.ugoe.cs.quest.plugin.mfc.MessageHandler#onParameter(java.lang.String
-	 * , java.lang.String)
-	 */
-	@Override
-	public void onParameter(String name, String value) {
-		if (name.equals("window.hwnd")) {
-			hwnd = Integer.parseInt(value);
-		}
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onParameter(java.lang.String ,
+     * java.lang.String)
+     */
+    @Override
+    public void onParameter(String name, String value) {
+        if (name.equals("window.hwnd")) {
+            hwnd = Long.parseLong(value);
+        }
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onStartElement()
-	 */
-	@Override
-	public void onStartElement() {
-		hwnd = 0;
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onStartElement()
+     */
+    @Override
+    public void onStartElement() {
+        hwnd = 0;
+    }
 
 }
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/HandlerSetText.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/HandlerSetText.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/HandlerSetText.java	(revision 619)
@@ -1,6 +1,6 @@
+
 package de.ugoe.cs.quest.plugin.mfc;
 
-import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowTree;
-import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowTreeNode;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.WindowTree;
 
 /**
@@ -14,65 +14,67 @@
 public class HandlerSetText extends MessageHandler {
 
-	/**
-	 * <p>
-	 * Constructor. Creates a new HanderSetText.
-	 * </p>
-	 */
-	public HandlerSetText() {
-		super();
-	}
+    /**
+     * <p>
+     * Constructor. Creates a new HanderSetText.
+     * </p>
+     * 
+     * @param windowTree
+     *            the tree of GUI element specifications to be created and adapted during parsing
+     */
+    public HandlerSetText(WindowTree windowTree) {
+        super(windowTree);
+    }
 
-	/**
-	 * <p>
-	 * New name of the window.
-	 * </p>
-	 */
-	private String windowName;
+    /**
+     * <p>
+     * New name of the window.
+     * </p>
+     */
+    private String windowName;
 
-	/**
-	 * <p>
-	 * HWND of the window.
-	 * </p>
-	 */
-	private int hwnd;
+    /**
+     * <p>
+     * HWND of the window.
+     * </p>
+     */
+    private long hwnd;
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onEndElement()
-	 */
-	@Override
-	public void onEndElement() {
-		if (hwnd != 0) {
-			WindowTreeNode node = WindowTree.getInstance().find(hwnd);
-			node.setName(windowName);
-		}
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onEndElement()
+     */
+    @Override
+    public void onEndElement() {
+        if (hwnd != 0) {
+            super.getWindowTree().setName(hwnd, windowName);
+        }
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * de.ugoe.cs.quest.plugin.mfc.MessageHandler#onParameter(java.lang.String
-	 * , java.lang.String)
-	 */
-	@Override
-	public void onParameter(String name, String value) {
-		if (name.equals("window.hwnd")) {
-			hwnd = Integer.parseInt(value);
-		} else if (name.equals("window.newText")) {
-			windowName = value;
-		}
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onParameter(java.lang.String ,
+     * java.lang.String)
+     */
+    @Override
+    public void onParameter(String name, String value) {
+        if (name.equals("window.hwnd")) {
+            hwnd = Long.parseLong(value);
+        }
+        else if (name.equals("window.newText")) {
+            windowName = value;
+        }
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onStartElement()
-	 */
-	@Override
-	public void onStartElement() {
-		windowName = "";
-		hwnd = 0;
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.plugin.mfc.MessageHandler#onStartElement()
+     */
+    @Override
+    public void onStartElement() {
+        windowName = "";
+        hwnd = 0;
+    }
 }
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/MFCLogParser.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/MFCLogParser.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/MFCLogParser.java	(revision 619)
@@ -1,2 +1,3 @@
+
 package de.ugoe.cs.quest.plugin.mfc;
 
@@ -8,6 +9,8 @@
 import java.security.InvalidParameterException;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.SortedMap;
 import java.util.TreeMap;
@@ -24,6 +27,9 @@
 
 import de.ugoe.cs.quest.eventcore.Event;
-import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowTree;
+import de.ugoe.cs.quest.eventcore.guimodel.GUIModel;
 import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowsMessage;
+import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowsMessageType;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.MFCGUIElement;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.WindowTree;
 import de.ugoe.cs.util.StringTools;
 import de.ugoe.cs.util.console.Console;
@@ -31,9 +37,8 @@
 /**
  * <p>
- * This class provides functionality to parse XML log files generated by the
- * MFCUsageMonitor of EventBench. The result of parsing a file is a collection
- * of event sequences. It uses the {@link SequenceSplitter} and the
- * {@link EventGenerator} as well as custom defined {@link MessageHandler} for
- * the parsing.
+ * This class provides functionality to parse XML log files generated by the MFCUsageMonitor of
+ * EventBench. The result of parsing a file is a collection of event sequences. It uses the
+ * {@link SequenceSplitter} and the {@link EventGenerator} as well as custom defined
+ * {@link MessageHandler} for the parsing.
  * </p>
  * 
@@ -43,235 +48,302 @@
 public class MFCLogParser extends DefaultHandler {
 
-	/**
-	 * <p>
-	 * If a custom message handler is used, this field contains its handle.
-	 * Otherwise this field is {@code null}.
-	 * </p>
-	 */
-	private MessageHandler currentHandler;
-
-	/**
-	 * <p>
-	 * Handle to the message that is currently parsed.
-	 * </p>
-	 */
-	private WindowsMessage currentMessage;
-
-	/**
-	 * <p>
-	 * {@link SequenceSplitter} instance used by the {@link MFCLogParser}.
-	 * </p>
-	 */
-	private SequenceSplitter sequenceSplitter;
-
-	/**
-	 * <p>
-	 * Collection of event sequences that is contained in the log file, which is
-	 * parsed.
-	 * </p>
-	 */
-	private Collection<List<Event>> sequences;
-
-	/**
-	 * <p>
-	 * Debugging variable that allows the analysis which message type occurs how
-	 * often in the log file. Can be used to enhance the message filter.
-	 * </p>
-	 */
-	private SortedMap<Integer, Integer> typeCounter;
-
-	/**
-	 * <p>
-	 * Debugging variable that enables the counting of the occurrences of each
-	 * message. Used in combination with {@link #typeCounter}.
-	 * </p>
-	 */
-	private boolean countMessageOccurences;
-
-	/**
-	 * <p>
-	 * Constructor. Creates a new LogParser that does not count message
-	 * occurrences.
-	 * </p>
-	 */
-	public MFCLogParser() {
-		this(false);
-	}
-
-	/**
-	 * <p>
-	 * Constructor. Creates a new LogParser.
-	 * </p>
-	 * 
-	 * @param countMessageOccurences
-	 *            if true, the occurrences of each message type in the log is
-	 *            counted.
-	 */
-	public MFCLogParser(boolean countMessageOccurences) {
-		sequenceSplitter = new SequenceSplitter();
-		sequences = new LinkedList<List<Event>>();
-		currentHandler = null;
-		this.countMessageOccurences = countMessageOccurences;
-		if (countMessageOccurences) {
-			typeCounter = new TreeMap<Integer, Integer>();
-		}
-
-	}
-
-	/**
-	 * <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;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
-	 * java.lang.String, java.lang.String, org.xml.sax.Attributes)
-	 */
-	@Override
-	public void startElement(String uri, String localName, String qName,
-			Attributes atts) throws SAXException {
-		if (qName.equals("session")) {
-			Console.traceln("start of session");
-			sequenceSplitter = new SequenceSplitter();
-		} else if (qName.equals("msg")) {
-			String msgType = atts.getValue("type");
-			int msgInt = -1;
-			try {
-				msgInt = Integer.parseInt(msgType);
-
-				if (countMessageOccurences) {
-					Integer currentCount = typeCounter.get(msgInt);
-					if (currentCount == null) {
-						typeCounter.put(msgInt, 1);
-					} else {
-						typeCounter.put(msgInt, currentCount + 1);
-					}
-				}
-
-				if (msgInt == MessageDefs.WM_CREATE) {
-					currentHandler = new HandlerCreate();
-					currentHandler.onStartElement();
-				} else if (msgInt == MessageDefs.WM_DESTROY) {
-					currentHandler = new HandlerDestroy();
-					currentHandler.onStartElement();
-				} else if (msgInt == MessageDefs.WM_SETTEXT) {
-					currentHandler = new HandlerSetText();
-					currentHandler.onStartElement();
-				} else {
-					currentMessage = new WindowsMessage(msgInt);
-				}
-			} catch (NumberFormatException e) {
-				Console.printerrln("Invalid message type: type not a number");
-				e.printStackTrace();
-			}
-		} else if (qName.equals("param")) {
-			if (currentHandler != null) {
-				currentHandler.onParameter(atts.getValue("name"),
-						atts.getValue("value"));
-			} else {
-				currentMessage.addParameter(atts.getValue("name"),
-						atts.getValue("value"));
-			}
-		}
-	}
-
-	/*
-	 * (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("msg")) {
-			if (currentHandler != null) {
-				currentHandler.onEndElement();
-				currentHandler = null;
-			} else {
-				try {
-					currentMessage.setTarget(WindowTree.getInstance());
-					sequenceSplitter.addMessage(currentMessage);
-				} catch (InvalidParameterException e) {
-					Console.traceln(e.getMessage() + " WindowsMessage "
-							+ currentMessage + " ignored.");
-				}
-			}
-		} else if (qName.equals("session")) {
-			sequenceSplitter.endSession();
-			List<Event> seq = sequenceSplitter.getSequence();
-			if( seq!=null && !seq.isEmpty() ) {
-				sequences.add(seq);
-			}
-			Console.traceln("end of session");
-		}
-	}
-
-	/**
-	 * <p>
-	 * Parses a given log file created by the MFCMonitor and adds its contents
-	 * to the collection of event sequences.
-	 * </p>
-	 * 
-	 * @param filename
-	 *            name and path of the log file
-	 */
-	public void parseFile(String filename) {
-		if (filename == null) {
-			throw new InvalidParameterException("filename must not be null");
-		}
-
-		SAXParserFactory spf = SAXParserFactory.newInstance();
-		spf.setValidating(true);
-
-		SAXParser saxParser = null;
-		InputSource inputSource = null;
-		try {
-			saxParser = spf.newSAXParser();
-			inputSource = new InputSource(new InputStreamReader(
-					new FileInputStream(filename)));//, "UTF-8"));
-		//} catch (UnsupportedEncodingException e) {
-		//	e.printStackTrace();
-		} catch (ParserConfigurationException e) {
-			e.printStackTrace();
-		} catch (SAXException e) {
-			e.printStackTrace();
-		} catch (FileNotFoundException e) {
-			e.printStackTrace();
-		}
-		if (inputSource != null) {
-			inputSource.setSystemId("file://"
-					+ new File(filename).getAbsolutePath());
-			try {
-				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()
-						+ ".");
-				e.printStackTrace();
-			} catch (SAXException e) {
-				e.printStackTrace();
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		}
-		if (countMessageOccurences) {
-			Console.println("Message statistics:");
-			Console.println(typeCounter.toString()
-					.replace(" ", StringTools.ENDLINE)
-					.replaceAll("[\\{\\}]", ""));
-		}
-	}
+    /**
+     * <p>
+     * If a custom message handler is used, this field contains its handle. Otherwise this field is
+     * {@code null}.
+     * </p>
+     */
+    private MessageHandler currentHandler;
+
+    /**
+     * <p>
+     * internal handle to the current window tree
+     * </p>
+     */
+    private WindowTree currentWindowTree;
+
+    /**
+     * <p>
+     * the type of the currently parsed message
+     * </p>
+     */
+    private WindowsMessageType currentMessageType;
+    
+    /**
+     * <p>
+     * the parameters of the currently parsed message
+     * </p>
+     */
+    private Map<String, Object> currentMessageParameters = new HashMap<String, Object>();
+    
+    /**
+     * <p>
+     * {@link SequenceSplitter} instance used by the {@link MFCLogParser}.
+     * </p>
+     */
+    private SequenceSplitter sequenceSplitter;
+
+    /**
+     * <p>
+     * Collection of message sequences that is contained in the log file, which is parsed.
+     * </p>
+     */
+    private Collection<List<Event>> sequences;
+
+    /**
+     * <p>
+     * Debugging variable that allows the analysis which message type occurs how often in the log
+     * file. Can be used to enhance the message filter.
+     * </p>
+     */
+    private SortedMap<WindowsMessageType, Integer> typeCounter;
+
+    /**
+     * <p>
+     * Debugging variable that enables the counting of the occurrences of each message. Used in
+     * combination with {@link #typeCounter}.
+     * </p>
+     */
+    private boolean countMessageOccurences;
+
+    /**
+     * <p>
+     * Constructor. Creates a new LogParser that does not count message occurrences.
+     * </p>
+     */
+    public MFCLogParser() {
+        this(false);
+    }
+
+    /**
+     * <p>
+     * Constructor. Creates a new LogParser.
+     * </p>
+     * 
+     * @param countMessageOccurences
+     *            if true, the occurrences of each message type in the log is counted.
+     */
+    public MFCLogParser(boolean countMessageOccurences) {
+        sequences = new LinkedList<List<Event>>();
+        currentHandler = null;
+        this.countMessageOccurences = countMessageOccurences;
+        if (countMessageOccurences) {
+            typeCounter = new TreeMap<WindowsMessageType, Integer>();
+        }
+    }
+
+    /**
+     * <p>
+     * Parses a log file written by the MFCMonitor 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 InvalidParameterException("filename must not be null");
+        }
+
+        parseFile(new File(filename));
+    }
+
+    /**
+     * <p>
+     * Parses a log file written by the MFCMonitor 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 InvalidParameterException("file must not be null");
+        }
+
+        SAXParserFactory spf = SAXParserFactory.newInstance();
+        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) {
+            // e.printStackTrace();
+        }
+        catch (ParserConfigurationException e) {
+            // TODO handle Exception
+            e.printStackTrace();
+        }
+        catch (SAXException e) {
+            // TODO handle Exception
+            e.printStackTrace();
+        }
+        catch (FileNotFoundException e) {
+            // TODO handle Exception
+            e.printStackTrace();
+        }
+        
+        if (inputSource != null) {
+            inputSource.setSystemId("file://" + file.getAbsolutePath());
+            try {
+                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() + ".");
+                e.printStackTrace();
+            }
+            catch (SAXException e) {
+                // TODO handle Exception
+                e.printStackTrace();
+            }
+            catch (IOException e) {
+                // TODO handle Exception
+                e.printStackTrace();
+            }
+        }
+        
+        if (countMessageOccurences) {
+            Console.println("Message statistics:");
+            Console.println
+                (typeCounter.toString().replace(" ", StringTools.ENDLINE).replaceAll("[\\{\\}]", ""));
+        }
+    }
+    
+    /**
+     * <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 collection of event sequences
+     */
+    public GUIModel getGuiModel() {
+        return currentWindowTree.getGUIModel();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String,
+     * java.lang.String, org.xml.sax.Attributes)
+     */
+    @Override
+    public void startElement(String uri, String localName, String qName, Attributes atts)
+        throws SAXException
+    {
+        if (qName.equals("session")) {
+            Console.traceln("start of session");
+            // in some logs, the session end may be marked in between the log. This is because
+            // of thread problems. So instead of creating a new GUI model, preserve it.
+            if (currentWindowTree == null) {
+                currentWindowTree = new WindowTree();
+            }
+            sequenceSplitter = new SequenceSplitter(currentWindowTree);
+        }
+        else if (qName.equals("msg")) {
+            currentMessageType = WindowsMessageType.parseMessageType(atts.getValue("type"));
+
+            if (countMessageOccurences) {
+                Integer currentCount = typeCounter.get(currentMessageType);
+                if (currentCount == null) {
+                    typeCounter.put(currentMessageType, 1);
+                }
+                else {
+                    typeCounter.put(currentMessageType, currentCount + 1);
+                }
+            }
+
+            if (currentMessageType == WindowsMessageType.WM_CREATE) {
+                currentHandler = new HandlerCreate(currentWindowTree);
+                currentHandler.onStartElement();
+            }
+            else if (currentMessageType == WindowsMessageType.WM_DESTROY) {
+                currentHandler = new HandlerDestroy(currentWindowTree);
+                currentHandler.onStartElement();
+            }
+            else if (currentMessageType == WindowsMessageType.WM_SETTEXT) {
+                currentHandler = new HandlerSetText(currentWindowTree);
+                currentHandler.onStartElement();
+            }
+        }
+        else if (qName.equals("param")) {
+            if (currentHandler != null) {
+                currentHandler.onParameter(atts.getValue("name"), atts.getValue("value"));
+            }
+            else {
+                // provide the parameters directly in the correct type
+                String paramName = atts.getValue("name");
+                if (("window.hwnd".equals(paramName)) ||
+                    ("source".equals(paramName)) ||
+                    ("LPARAM".equals(paramName)) ||
+                    ("WPARAM".equals(paramName)) ||
+                    ("scrollPos".equals(paramName)) ||
+                    ("scrollBarHandle".equals(paramName)))
+                {
+                    Long paramValue = Long.parseLong(atts.getValue("value"));
+                    currentMessageParameters.put(paramName, paramValue);
+                }
+                else {
+                    currentMessageParameters.put(paramName, atts.getValue("value"));
+                }
+            }
+        }
+    }
+
+    /*
+     * (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("msg")) {
+            if (currentHandler != null) {
+                currentHandler.onEndElement();
+                currentHandler = null;
+            }
+            else {
+                try {
+                    long hwnd = (Long) currentMessageParameters.get("window.hwnd");
+                    MFCGUIElement target = currentWindowTree.find(hwnd);
+                    
+                    WindowsMessage message = new WindowsMessage
+                        (currentMessageType, target, currentMessageParameters);
+                    
+                    sequenceSplitter.addMessage(message);
+                }
+                catch (InvalidParameterException e) {
+                    Console.traceln(e.getMessage() + " WindowsMessage " + currentMessageType +
+                                    " ignored.");
+                }
+            }
+        }
+        else if (qName.equals("session")) {
+            sequenceSplitter.endSession();
+            List<Event> seq = sequenceSplitter.getSequence();
+            if (seq != null && !seq.isEmpty()) {
+                sequences.add(seq);
+            }
+            Console.traceln("end of session");
+        }
+    }
+
 }
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/MessageDefs.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/MessageDefs.java	(revision 581)
+++ 	(revision )
@@ -1,167 +1,0 @@
-package de.ugoe.cs.quest.plugin.mfc;
-
-/**
- * <p>
- * Contains definitions of windows message codes, such that they can be used
- * internally by their name and not their integer value, to improve the
- * readability of the source code.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- */
-public interface MessageDefs {
-
-	public static final int WM_NULL = 0;
-	public static final int WM_CREATE = 1;
-	public static final int WM_DESTROY = 2;
-	public static final int WM_MOVE = 3;
-	public static final int WM_SIZE = 5;
-	public static final int WM_ACTIVATE = 6;
-	public static final int WM_SETFOCUS = 7;
-	public static final int WM_KILLFOCUS = 8;
-	public static final int WM_ENABLE = 10;
-	public static final int WM_SETREDRAW = 11;
-	public static final int WM_SETTEXT = 12;
-	public static final int WM_GETTEXT = 13;
-	public static final int WM_GETTEXTLENGTH = 14;
-	public static final int WM_PAINT = 15;
-	public static final int WM_CLOSE = 16;
-	public static final int WM_QUERYENDSESSION = 17;
-	public static final int WM_QUIT = 18;
-	public static final int WM_QUERYOPEN = 19;
-	public static final int WM_ERASEBKGND = 20;
-	public static final int WM_SYSCOLORCHANGE = 21;
-	public static final int WM_ENDSESSION = 22;
-	public static final int WM_SHOWWINDOW = 24;
-	public static final int WM_CTLCOLOR = 25;
-	public static final int WM_WININICHANGE = 26;
-	public static final int WM_DEVMODECHANGE = 27;
-	public static final int WM_ACTIVATEAPP = 28;
-	public static final int WM_FONTCHANGE = 29;
-	public static final int WM_TIMECHANGE = 30;
-	public static final int WM_CANCELMODE = 31;
-	public static final int WM_SETCURSOR = 32;
-	public static final int WM_MOUSEACTIVATE = 33;
-	public static final int WM_CHILDACTIVATE = 34;
-	public static final int WM_QUEUESYNC = 35;
-	public static final int WM_GETMINMAXINFO = 36;
-	public static final int WM_PAINTICON = 38;
-	public static final int WM_ICONERASEBKGND = 39;
-	public static final int WM_NEXTDLGCTL = 40;
-	public static final int WM_SPOOLERSTATUS = 42;
-	public static final int WM_DRAWITEM = 43;
-	public static final int WM_MEASUREITEM = 44;
-	public static final int WM_DELETEITEM = 45;
-	public static final int WM_VKEYTOITEM = 46;
-	public static final int WM_CHARTOITEM = 47;
-	public static final int WM_SETFONT = 48;
-	public static final int WM_GETFONT = 49;
-	public static final int WM_SETHOTKEY = 50;
-	public static final int WM_GETHOTKEY = 51;
-	public static final int WM_QUERYDRAGICON = 55;
-	public static final int WM_COMPAREITEM = 57;
-	public static final int WM_GETOBJECT = 61;
-	public static final int WM_COMPACTING = 65;
-	public static final int WM_COMMNOTIFY = 68;
-	public static final int WM_WINDOWPOSCHANGING = 70;
-	public static final int WM_WINDOWPOSCHANGED = 71;
-	public static final int WM_POWER = 72;
-	public static final int WM_COPYDATA = 74;
-	public static final int WM_CANCELJOURNAL = 75;
-	public static final int WM_NOTIFY = 78;
-	public static final int WM_INPUTLANGCHANGEREQUEST = 80;
-	public static final int WM_INPUTLANGCHANGE = 81;
-	public static final int WM_TCARD = 82;
-	public static final int WM_HELP = 83;
-	public static final int WM_USERCHANGED = 84;
-	public static final int WM_NOTIFYFORMAT = 85;
-	public static final int WM_CONTEXTMENU = 123;
-	public static final int WM_STYLECHANGING = 124;
-	public static final int WM_STYLECHANGED = 125;
-	public static final int WM_DISPLAYCHANGE = 126;
-	public static final int WM_GETICON = 127;
-	public static final int WM_SETICON = 128;
-	public static final int WM_NCCREATE = 129;
-	public static final int WM_NCDESTROY = 130;
-	public static final int WM_NCCALCSIZE = 131;
-	public static final int WM_NCHITTEST = 132;
-	public static final int WM_NCPAINT = 133;
-	public static final int WM_NCACTIVATE = 134;
-	public static final int WM_GETDLGCODE = 135;
-	public static final int WM_SYNCPAINT = 136;
-	public static final int WM_NCMOUSEMOVE = 160;
-	public static final int WM_NCLBUTTONDOWN = 161;
-	public static final int WM_NCLBUTTONUP = 162;
-	public static final int WM_NCLBUTTONDBLCLK = 163;
-	public static final int WM_NCRBUTTONDOWN = 164;
-	public static final int WM_NCRBUTTONUP = 165;
-	public static final int WM_NCRBUTTONDBLCLK = 166;
-	public static final int WM_NCMBUTTONDOWN = 167;
-	public static final int WM_NCMBUTTONUP = 168;
-	public static final int WM_NCMBUTTONDBLCLK = 169;
-	public static final int WM_NCXBUTTONDOWN = 171;
-	public static final int WM_NCXBUTTONUP = 172;
-	public static final int WM_NCXBUTTONDBLCLK = 173;
-	public static final int WM_INPUT = 255;
-	public static final int WM_KEYDOWN = 256;
-	public static final int WM_KEYFIRST = 256;
-	public static final int WM_KEYUP = 257;
-	public static final int WM_CHAR = 258;
-	public static final int WM_DEADCHAR = 259;
-	public static final int WM_SYSKEYDOWN = 260;
-	public static final int WM_SYSKEYUP = 261;
-	public static final int WM_SYSCHAR = 262;
-	public static final int WM_SYSDEADCHAR = 263;
-	public static final int WM_KEYLAST = 264;
-	public static final int WM_WNT_CONVERTREQUESTEX = 265;
-	public static final int WM_CONVERTREQUEST = 266;
-	public static final int WM_CONVERTRESULT = 267;
-	public static final int WM_INTERIM = 268;
-	public static final int WM_IME_STARTCOMPOSITION = 269;
-	public static final int WM_IME_ENDCOMPOSITION = 270;
-	public static final int WM_IME_COMPOSITION = 271;
-	public static final int WM_IME_KEYLAST = 271;
-	public static final int WM_INITDIALOG = 272;
-	public static final int WM_COMMAND = 273;
-	public static final int WM_SYSCOMMAND = 274;
-	public static final int WM_TIMER = 275;
-	public static final int WM_HSCROLL = 276;
-	public static final int WM_VSCROLL = 277;
-	public static final int WM_INITMENU = 278;
-	public static final int WM_INITMENUPOPUP = 279;
-	public static final int WM_MENUSELECT = 287;
-	public static final int WM_MENUCHAR = 288;
-	public static final int WM_ENTERIDLE = 289;
-	public static final int WM_MENURBUTTONUP = 290;
-	public static final int WM_MENUDRAG = 291;
-	public static final int WM_MENUGETOBJECT = 292;
-	public static final int WM_UNINTMENUPOPUP = 293;
-	public static final int WM_MENUCOMMAND = 294;
-	public static final int WM_CHANGEUISTATE = 295;
-	public static final int WM_UPDATEUISTATE = 296;
-	public static final int WM_QUERYUISTATE = 297;
-	public static final int WM_CTLCOLORMSGBOX = 306;
-	public static final int WM_CTLCOLOREDIT = 307;
-	public static final int WM_CTLCOLORLISTBOX = 308;
-	public static final int WM_CTLCOLORBTN = 309;
-	public static final int WM_CTLCLOLORDLG = 310;
-	public static final int WM_CTLCOLORSCROLLBAR = 311;
-	public static final int WM_CTLCOLORSTATIC = 312;
-	public static final int WM_MOUSEFIRST = 512;
-	public static final int WM_MOUSEMOVE = 512;
-	public static final int WM_LBUTTONDOWN = 513;
-	public static final int WM_LBUTTONUP = 514;
-	public static final int WM_LBUTTONDBLCLK = 515;
-	public static final int WM_RBUTTONDOWN = 516;
-	public static final int WM_RBUTTONUP = 517;
-	public static final int WM_RBUTTONDBLCLK = 518;
-	public static final int WM_MBUTTONDOWN = 519;
-	public static final int WM_MBUTTONUP = 520;
-	public static final int WM_MBUTTONDBLCLK = 521;
-	public static final int WM_MOUSELAST = 521;
-	public static final int WM_MOUSEWHEEL = 522;
-	public static final int WM_XBUTTONDOWN = 523;
-	public static final int WM_XBUTTONUP = 524;
-	public static final int WM_XBUTTONDBLCLK = 525;
-}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/MessageHandler.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/MessageHandler.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/MessageHandler.java	(revision 619)
@@ -1,10 +1,12 @@
+
 package de.ugoe.cs.quest.plugin.mfc;
+
+import de.ugoe.cs.quest.plugin.mfc.guimodel.WindowTree;
 
 /**
  * <p>
- * Base class to define custom message handlers, for messages that shall be
- * handled differently during the parsing of usage logs. It provides dummy
- * implementations for all required methods, such that implementations can only
- * overwrite the parts they actually require and ignore the rest.
+ * Base class to define custom message handlers, for messages that shall be handled differently
+ * during the parsing of usage logs. It provides dummy implementations for all required methods,
+ * such that implementations can only overwrite the parts they actually require and ignore the rest.
  * </p>
  * 
@@ -14,42 +16,56 @@
 public class MessageHandler {
 
-	/**
-	 * <p>
-	 * Constructor. Protected to prohibit initialization of the base class
-	 * itself.
-	 * </p>
-	 */
-	protected MessageHandler() {
-	}
+    /**
+     * <p>
+     * during parsing, a tree of GUI elements is created and adapted.
+     * This is the reference to it.
+     * </p>
+     */
+    private WindowTree windowTree;
 
-	/**
-	 * <p>
-	 * Called in the startElement() method of the {@link MFCLogParser} when a
-	 * msg-node begins.
-	 * </p>
-	 */
-	public void onStartElement() {
-	}
+    /**
+     * <p>
+     * Constructor. Protected to prohibit initialization of the base class itself.
+     * </p>
+     * 
+     * @param windowTree the tree of GUI element specifications to be created and adapted during
+     *                   parsing
+     */
+    protected MessageHandler(WindowTree windowTree) {
+        this.windowTree = windowTree;
+    }
 
-	/**
-	 * <p>
-	 * Called by the {@link MFCLogParser} to handle param-nodes.
-	 * </p>
-	 * 
-	 * @param name
-	 *            name (type) of the parameter
-	 * @param value
-	 *            value of the parameter
-	 */
-	public void onParameter(String name, String value) {
-	}
+    /**
+     * <p>
+     * Called in the startElement() method of the {@link MFCLogParser} when a msg-node begins.
+     * </p>
+     */
+    public void onStartElement() {}
 
-	/**
-	 * <p>
-	 * Called in the endElement() method of {@link MFCLogParser} when a msg-node
-	 * ends.
-	 * </p>
-	 */
-	public void onEndElement() {
-	}
+    /**
+     * <p>
+     * Called by the {@link MFCLogParser} to handle param-nodes.
+     * </p>
+     * 
+     * @param name
+     *            name (type) of the parameter
+     * @param value
+     *            value of the parameter
+     */
+    public void onParameter(String name, String value) {}
+
+    /**
+     * <p>
+     * Called in the endElement() method of {@link MFCLogParser} when a msg-node ends.
+     * </p>
+     */
+    public void onEndElement() {}
+
+    /**
+     * @return the window tree created and adapted during parsing
+     */
+    protected WindowTree getWindowTree() {
+        return windowTree;
+    }
+    
 }
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/SequenceSplitter.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/SequenceSplitter.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/SequenceSplitter.java	(revision 619)
@@ -1,2 +1,3 @@
+
 package de.ugoe.cs.quest.plugin.mfc;
 
@@ -6,10 +7,12 @@
 import de.ugoe.cs.quest.eventcore.Event;
 import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowsMessage;
+import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowsMessageType;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.WindowTree;
 import de.ugoe.cs.util.console.Console;
 
 /**
  * <p>
- * Responsible to split sequences into subsequences, such that each subsequences
- * contains exactly one event.
+ * Responsible to split sequences into subsequences, such that each subsequences contains exactly
+ * one event.
  * </p>
  * 
@@ -19,268 +22,154 @@
 public class SequenceSplitter {
 
-	/**
-	 * <p>
-	 * Contains the current subsequence.
-	 * </p>
-	 */
-	private List<WindowsMessage> currentSequence;
+    /**
+     * <p>
+     * Contains the current subsequence.
+     * </p>
+     */
+    private List<WindowsMessage> currentSequence;
 
-	/**
-	 * <p>
-	 * Number of messages in the current sequences, that signal that a key or
-	 * mouse button has been pressed down to which not yet a message has been
-	 * found, that signals that the button has been released.
-	 * </p>
-	 */
-	private int openDowns;
+    /**
+     * <p>
+     * Number of messages in the current sequences, that signal that a key or mouse button has been
+     * pressed down to which not yet a message has been found, that signals that the button has been
+     * released.
+     * </p>
+     */
+    private int openDowns;
 
-	/**
-	 * <p>
-	 * Internal flag that signals if {@link #currentSequence} needs to be
-	 * initialized.
-	 * </p>
-	 */
-	private boolean initMessages;
+    /**
+     * <p>
+     * Internal flag that signals if {@link #currentSequence} needs to be initialized.
+     * </p>
+     */
+    private boolean initMessages;
 
-	/**
-	 * <p>
-	 * The {@link EventGenerator} used to convert the subsequences into
-	 * {@link Event}s
-	 * </p>
-	 */
-	private EventGenerator tokenGenerator;
+    /**
+     * <p>
+     * The {@link EventGenerator} used to convert the subsequences into {@link Event}s
+     * </p>
+     */
+    private EventGenerator tokenGenerator;
 
-	/**
-	 * <p>
-	 * The event sequence generated.
-	 * </p>
-	 */
-	private List<Event> actionSequence;
+    /**
+     * <p>
+     * The event sequence generated.
+     * </p>
+     */
+    private List<Event> actionSequence;
 
-	/**
-	 * <p>
-	 * Type of the previous message.
-	 * </p>
-	 */
-	private int prevMsg = 0;
+    /**
+     * <p>
+     * Type of the previous message.
+     * </p>
+     */
+    private WindowsMessageType prevMsg;
 
-	/**
-	 * <p>
-	 * Constructor. Creates a new SequenceSplitter.
-	 * </p>
-	 */
-	public SequenceSplitter() {
-		currentSequence = new LinkedList<WindowsMessage>();
-		openDowns = 0;
-		initMessages = true;
-		tokenGenerator = new EventGenerator();
-		actionSequence = new LinkedList<Event>();
-		prevMsg = 0;
-	}
+    /**
+     * <p>
+     * Constructor. Creates a new SequenceSplitter.
+     * </p>
+     */
+    public SequenceSplitter(WindowTree windowTree) {
+        currentSequence = new LinkedList<WindowsMessage>();
+        openDowns = 0;
+        initMessages = true;
+        tokenGenerator = new EventGenerator(windowTree);
+        actionSequence = new LinkedList<Event>();
+        prevMsg = null;
+    }
 
-	/**
-	 * <p>
-	 * Called by the {@link MFCLogParser} every time a message is parsed.
-	 * </p>
-	 * 
-	 * @param msg
-	 *            message to be added
-	 */
-	public void addMessage(WindowsMessage msg) {
-		if (startOfSequence(msg)) {
-			if (!initMessages) {
-				Event currentAction = tokenGenerator
-						.generateEvent(currentSequence);
-				if (currentAction != null) {
-					actionSequence.add(currentAction);
-				}
-				if (isKeyMessage(msg.getType()) && openDowns > 0) {
-					Console.traceln("Key message found with open down mouse messages - will probabably result in a faulty sequence.");
-				}
-			} else {
-				initMessages = false;
-			}
-			currentSequence = new LinkedList<WindowsMessage>();
-		}
-		if (isUpMessage(msg.getType())) {
-			if (openDowns > 0) {
-				openDowns--;
-			}
-		}
+    /**
+     * <p>
+     * Called by the {@link MFCLogParser} every time a message is parsed.
+     * </p>
+     * 
+     * @param msg
+     *            message to be added
+     */
+    public void addMessage(WindowsMessage msg) {
+        if (startOfSequence(msg)) {
+            if (!initMessages) {
+                Event currentAction = tokenGenerator.generateEvent(currentSequence);
+                if (currentAction != null) {
+                    actionSequence.add(currentAction);
+                }
+                if (msg.getType().isKeyMessage() && openDowns > 0) {
+                    Console
+                        .traceln("Key message found with open down mouse messages - will probabably result in a faulty sequence.");
+                }
+            }
+            else {
+                initMessages = false;
+            }
+            currentSequence = new LinkedList<WindowsMessage>();
+        }
+        if (msg.getType().isUpMessage()) {
+            if (openDowns > 0) {
+                openDowns--;
+            }
+        }
 
-		// this fix checks if there are two consecutive mouse-down messages.
-		// This sometimes occurs due to incorrect filtering in the monitoring
-		// dll.
-		if (!(prevMsg == MessageDefs.WM_LBUTTONDOWN && prevMsg == msg.getType())) {
-			currentSequence.add(msg);
-		} else {
-			openDowns--;
-		}
-		prevMsg = msg.getType();
-	}
+        // this fix checks if there are two consecutive mouse-down messages.
+        // This sometimes occurs due to incorrect filtering in the monitoring
+        // dll.
+        if (!(prevMsg == WindowsMessageType.WM_LBUTTONDOWN && prevMsg == msg.getType())) {
+            currentSequence.add(msg);
+        }
+        else {
+            openDowns--;
+        }
+        prevMsg = msg.getType();
+    }
 
-	/**
-	 * <p>
-	 * Returns the event sequence generated from the message that have been
-	 * added.
-	 * </p>
-	 * 
-	 * @return generated event sequence
-	 */
-	public List<Event> getSequence() {
-		return actionSequence;
-	}
+    /**
+     * <p>
+     * Returns the event sequence generated from the message that have been added.
+     * </p>
+     * 
+     * @return generated event sequence
+     */
+    public List<Event> getSequence() {
+        return actionSequence;
+    }
 
-	/**
-	 * <p>
-	 * Called when a session in the log file is finished, i.e., a closing
-	 * session-node is found.
-	 * </p>
-	 */
-	public void endSession() {
-		Event currentAction = tokenGenerator
-				.generateEvent(currentSequence);
-		if (currentAction != null) {
-			actionSequence.add(currentAction);
-		}
-	}
+    /**
+     * <p>
+     * Called when a session in the log file is finished, i.e., a closing session-node is found.
+     * </p>
+     */
+    public void endSession() {
+        Event currentAction = tokenGenerator.generateEvent(currentSequence);
+        if (currentAction != null) {
+            actionSequence.add(currentAction);
+        }
+    }
 
-	/**
-	 * <p>
-	 * Checks if the message starts a new subsequence and returns the result.
-	 * </p>
-	 * 
-	 * @param msg
-	 *            message that is checked
-	 * @return true, if a new subsequence begins
-	 */
-	private boolean startOfSequence(WindowsMessage msg) {
-		boolean isStart = false;
-		int msgType = msg.getType();
-		if (isKeyMessage(msgType)) {
-			isStart = true;
-		}
-		if (isDownMessage(msgType)) {
-			openDowns++;
-			if (openDowns == 1) {
-				isStart = true;
-			}
-		}
-		if (isDblclkMessage(msgType)) {
-			openDowns++;
-		}
-		return isStart;
-	}
-
-	/**
-	 * <p>
-	 * Checks if the type of a message is generated is a keyboard interaction.
-	 * </p>
-	 * 
-	 * @param msgType
-	 *            type of the message
-	 * @return true if it is a keyboard interaction; false otherwise
-	 */
-	private boolean isKeyMessage(int msgType) {
-		boolean isKeyMsg = false;
-		switch (msgType) {
-		case MessageDefs.WM_KEYDOWN:
-		case MessageDefs.WM_KEYUP:
-		case MessageDefs.WM_SYSKEYDOWN:
-		case MessageDefs.WM_SYSKEYUP:
-			isKeyMsg = true;
-			break;
-		default:
-			break;
-		}
-		return isKeyMsg;
-	}
-
-	/**
-	 * <p>
-	 * Checks if the type of a message indicates that the mouse has been pressed
-	 * down.
-	 * </p>
-	 * 
-	 * @param msgType
-	 *            type of the message
-	 * @return true if it is mouse-down message; false otherwise
-	 */
-	private boolean isDownMessage(int msgType) {
-		boolean isDownMsg = false;
-		switch (msgType) {
-		case MessageDefs.WM_LBUTTONDOWN:
-		case MessageDefs.WM_RBUTTONDOWN:
-		case MessageDefs.WM_MBUTTONDOWN:
-		case MessageDefs.WM_XBUTTONDOWN:
-		case MessageDefs.WM_NCLBUTTONDOWN:
-		case MessageDefs.WM_NCRBUTTONDOWN:
-		case MessageDefs.WM_NCMBUTTONDOWN:
-		case MessageDefs.WM_NCXBUTTONDOWN:
-			isDownMsg = true;
-			break;
-		default:
-			break;
-		}
-		return isDownMsg;
-	}
-
-	/**
-	 * <p>
-	 * Checks if the type of a message indicates that a double click has been
-	 * performed.
-	 * </p>
-	 * 
-	 * @param msgType
-	 *            type of the message
-	 * @return true if it is a double click message; false otherwise
-	 */
-	private boolean isDblclkMessage(int msgType) {
-		boolean isDblclkMsg = false;
-		switch (msgType) {
-		case MessageDefs.WM_LBUTTONDBLCLK:
-		case MessageDefs.WM_RBUTTONDBLCLK:
-		case MessageDefs.WM_MBUTTONDBLCLK:
-		case MessageDefs.WM_XBUTTONDBLCLK:
-		case MessageDefs.WM_NCLBUTTONDBLCLK:
-		case MessageDefs.WM_NCRBUTTONDBLCLK:
-		case MessageDefs.WM_NCMBUTTONDBLCLK:
-		case MessageDefs.WM_NCXBUTTONDBLCLK:
-			isDblclkMsg = true;
-			break;
-		default:
-			break;
-		}
-		return isDblclkMsg;
-	}
-
-	/**
-	 * <p>
-	 * Checks if the type of a message indicates that the mouse has been
-	 * released.
-	 * </p>
-	 * 
-	 * @param msgType
-	 *            type of the message
-	 * @return true if it is mouse-up message; false otherwise
-	 */
-	private boolean isUpMessage(int msgType) {
-		boolean isUpMsg = false;
-		switch (msgType) {
-		case MessageDefs.WM_LBUTTONUP:
-		case MessageDefs.WM_RBUTTONUP:
-		case MessageDefs.WM_MBUTTONUP:
-		case MessageDefs.WM_XBUTTONUP:
-		case MessageDefs.WM_NCLBUTTONUP:
-		case MessageDefs.WM_NCRBUTTONUP:
-		case MessageDefs.WM_NCMBUTTONUP:
-		case MessageDefs.WM_NCXBUTTONUP:
-			isUpMsg = true;
-			break;
-		default:
-			break;
-		}
-		return isUpMsg;
-	}
+    /**
+     * <p>
+     * Checks if the message starts a new subsequence and returns the result.
+     * </p>
+     * 
+     * @param msg
+     *            message that is checked
+     * @return true, if a new subsequence begins
+     */
+    private boolean startOfSequence(WindowsMessage msg) {
+        boolean isStart = false;
+        WindowsMessageType msgType = msg.getType();
+        if (msgType.isKeyMessage()) {
+            isStart = true;
+        }
+        if (msgType.isDownMessage()) {
+            openDowns++;
+            if (openDowns == 1) {
+                isStart = true;
+            }
+        }
+        if (msgType.isDblclkMessage()) {
+            openDowns++;
+        }
+        return isStart;
+    }
 
 }
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/commands/CMDparseXML.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/commands/CMDparseXML.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/commands/CMDparseXML.java	(revision 619)
@@ -1,2 +1,3 @@
+
 package de.ugoe.cs.quest.plugin.mfc.commands;
 
@@ -4,11 +5,9 @@
 import java.util.Collection;
 import java.util.List;
-import java.util.SortedSet;
 
 import de.ugoe.cs.quest.CommandHelpers;
 import de.ugoe.cs.quest.eventcore.Event;
+import de.ugoe.cs.quest.eventcore.guimodel.GUIModel;
 import de.ugoe.cs.quest.plugin.mfc.MFCLogParser;
-import de.ugoe.cs.quest.plugin.mfc.eventcore.MFCTargetComparator;
-import de.ugoe.cs.quest.plugin.mfc.eventcore.WindowTree;
 import de.ugoe.cs.quest.ui.GlobalDataContainer;
 import de.ugoe.cs.util.console.Command;
@@ -17,6 +16,5 @@
 /**
  * <p>
- * Command to parse an XML file with sessions monitored by EventBench's
- * MFCUsageMonitor.
+ * Command to parse an XML file with sessions monitored by EventBench's MFCUsageMonitor.
  * </p>
  * 
@@ -26,64 +24,52 @@
 public class CMDparseXML implements Command {
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see de.ugoe.cs.util.console.Command#help()
-	 */
-	@Override
-	public void help() {
-		Console.println("Usage: parseXML <filename> {<sequencesName>} {<countMessageOccurences>}");
-	}
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.util.console.Command#help()
+     */
+    @Override
+    public void help() {
+        Console.println("Usage: parseXML <filename> {<sequencesName>} {<countMessageOccurences>}");
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see de.ugoe.cs.util.console.Command#run(java.util.List)
-	 */
-	@Override
-	public void run(List<Object> parameters) {
-		String filename;
-		String sequencesName = "sequences";
-		boolean countMessageOccurences = false;
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
+     */
+    @Override
+    public void run(List<Object> parameters) {
+        String filename;
+        String sequencesName = "sequences";
+        boolean countMessageOccurences = false;
 
-		try {
-			filename = (String) parameters.get(0);
-			if (parameters.size() >= 2) {
-				sequencesName = (String) parameters.get(1);
-			}
-			if (parameters.size() >= 3) {
-				countMessageOccurences = Boolean
-						.parseBoolean((String) parameters.get(2));
-			}
-		} catch (Exception e) {
-			throw new InvalidParameterException();
-		}
+        try {
+            filename = (String) parameters.get(0);
+            if (parameters.size() >= 2) {
+                sequencesName = (String) parameters.get(1);
+            }
+            if (parameters.size() >= 3) {
+                countMessageOccurences = Boolean.parseBoolean((String) parameters.get(2));
+            }
+        }
+        catch (Exception e) {
+            throw new InvalidParameterException();
+        }
 
-		MFCLogParser parser = new MFCLogParser(countMessageOccurences);
-		parser.parseFile(filename);
+        MFCLogParser parser = new MFCLogParser(countMessageOccurences);
+        parser.parseFile(filename);
 
-		Collection<List<Event>> sequences = parser.getSequences();
-		
-		Console.traceln("Pre-computing event target equalities.");
-		// compare all Events to a dummy event to make sure they are known by
-		// the MFCTargetComparator
-		Event dummyEvent = Event.STARTEVENT;
-		for (List<Event> sequence : sequences) {
-			for (Event event : sequence) {
-				event.equals(dummyEvent);
-			}
-		}
-		MFCTargetComparator.setMutable(false);
-		
-		SortedSet<String> targets = WindowTree.getInstance().getTargets();
+        Collection<List<Event>> sequences = parser.getSequences();
 
-		if (GlobalDataContainer.getInstance().addData(sequencesName, sequences)) {
-			CommandHelpers.dataOverwritten(sequencesName);
-		}
-		if (GlobalDataContainer.getInstance().addData(
-				sequencesName + "_targets", targets)) {
-			CommandHelpers.dataOverwritten(sequencesName + "_targets");
-		}
-	}
+        GUIModel targets = parser.getGuiModel();
+
+        if (GlobalDataContainer.getInstance().addData(sequencesName, sequences)) {
+            CommandHelpers.dataOverwritten(sequencesName);
+        }
+        if (GlobalDataContainer.getInstance().addData(sequencesName + "_targets", targets)) {
+            CommandHelpers.dataOverwritten(sequencesName + "_targets");
+        }
+    }
 
 }
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEvent.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEvent.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEvent.java	(revision 619)
@@ -0,0 +1,83 @@
+
+package de.ugoe.cs.quest.plugin.mfc.eventcore;
+
+import de.ugoe.cs.quest.eventcore.Event;
+import de.ugoe.cs.quest.eventcore.IEventType;
+import de.ugoe.cs.quest.eventcore.guimodel.GUIModel;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.MFCGUIElement;
+
+/**
+ * <p>
+ * Contains all informations about a windows message, i.e., all parameters that are read when a
+ * windows message is parsed as well as its target, hwnd, etc.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ * 
+ */
+public class MFCEvent extends Event {
+
+    /**
+     * <p>
+     * Id for object serialization.
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param eventType
+     * @param target
+     * @param currentMessageParameters
+     */
+    public MFCEvent(IEventType    eventType,
+                    MFCGUIElement target,
+                    GUIModel      guiModel)
+    {
+        super(eventType);
+        super.setTarget(target);
+    }
+
+    /**
+     * <p>
+     * Two {@link WindowsMessage} are equal, if their {@link #type}, {@link #xmlWindowDescription},
+     * and {@link #params} are equal.
+     * </p>
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        boolean isEqual = false;
+        if (other instanceof MFCEvent) {
+            isEqual =
+                ((MFCEvent) other).type == this.type &&
+                ((MFCEvent) other).target.equals(this.target);
+        }
+        return isEqual;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        int multiplier = 17;
+        int hash = 42;
+
+        hash = multiplier * hash + type.hashCode();
+        hash = multiplier * hash + target.hashCode();
+
+        return hash;
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEventTarget.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEventTarget.java	(revision 581)
+++ 	(revision )
@@ -1,46 +1,0 @@
-
-package de.ugoe.cs.quest.plugin.mfc.eventcore;
-
-import de.ugoe.cs.quest.eventcore.IEventTarget;
-
-/**
- * 
- * <p>
- * TODO comment
- * </p>
- * 
- * @version $Revision: $ $Date: Aug 17, 2012$
- * @author 2012, last modified by $Author: sherbold$
- */
-public class MFCEventTarget implements IEventTarget {
-
-    /**  */
-    private static final long serialVersionUID = 1L;
-
-    private String targetString;
-
-    public MFCEventTarget(String targetString) {
-        this.targetString = targetString;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see de.ugoe.cs.quest.eventcore.IEventTarget#getPlatform()
-     */
-    @Override
-    public String getPlatform() {
-        return "MFC";
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return targetString;
-    }
-
-}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEventType.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEventType.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEventType.java	(revision 619)
@@ -1,3 +1,7 @@
-
+// Module    : $RCSfile: MFCEventType.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 21.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
 package de.ugoe.cs.quest.plugin.mfc.eventcore;
 
@@ -9,46 +13,32 @@
  * </p>
  * 
- * @version $Revision: $ $Date: Aug 17, 2012$
- * @author 2012, last modified by $Author: sherbold$
+ * @version $Revision: $ $Date: 21.08.2012$
+ * @author 2012, last modified by $Author: pharms$
  */
 public class MFCEventType implements IEventType {
 
-    /**  */
+    /** */
     private static final long serialVersionUID = 1L;
+    
+    /** */
+    private WindowsMessageType messageType;
 
-    private final String typeString;
-    
-    private String info = null;
-
-    public MFCEventType(String typeString) {
-        this.typeString = typeString;
-    }
-    
-    public void setInfo(String info) {
-        this.info = info;
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param currentMessageType
+     */
+    public MFCEventType(WindowsMessageType messageType) {
+        this.messageType = messageType;
     }
 
-    /*
-     * (non-Javadoc)
-     * 
+    /* (non-Javadoc)
      * @see de.ugoe.cs.quest.eventcore.IEventType#getName()
      */
     @Override
     public String getName() {
-        return "MFCEventType";
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        String str = typeString;
-        if( info!=null ) {
-            str += "." + info;
-        }
-        return str;
+        return messageType.name();
     }
 
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEventTypeFactory.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEventTypeFactory.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCEventTypeFactory.java	(revision 619)
@@ -0,0 +1,186 @@
+// Module    : $RCSfile: EventTypeFactory.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 21.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.eventcore;
+
+import java.util.Map;
+
+import de.ugoe.cs.quest.eventcore.IEventType;
+import de.ugoe.cs.quest.eventcore.gui.KeyPressed;
+import de.ugoe.cs.quest.eventcore.gui.KeyReleased;
+import de.ugoe.cs.quest.eventcore.gui.KeyboardFocusChange;
+import de.ugoe.cs.quest.eventcore.gui.MouseButtonInteraction;
+import de.ugoe.cs.quest.eventcore.gui.MouseClick;
+import de.ugoe.cs.quest.eventcore.gui.ValueSelection;
+import de.ugoe.cs.tasktree.keyboardmaps.VirtualKey;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 21.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCEventTypeFactory {
+    
+    /**
+     * <p>
+     * the instance of the singleton
+     * </p>
+     */
+    private static MFCEventTypeFactory instance = new MFCEventTypeFactory();
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     */
+    private MFCEventTypeFactory() {
+        // prevent external instantiation
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @return
+     */
+    public static MFCEventTypeFactory getInstance() {
+        return instance;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param currentRuleName
+     * @return
+     */
+    public IEventType getEventType(String              eventName,
+                                   Map<String, String> messageParameters)
+    {
+        if ("LeftClickButton".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("LeftClickListBox".equals(eventName)) {
+            return new ValueSelection<Integer>(getSelectedValue(messageParameters));
+        }
+        else if ("TabChange".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("LeftClickCommand".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("LeftClickSysCommand".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("NCLeftClickSysCommand".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("LeftClickMenuItemCmd".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("HScroll_TrackBar".equals(eventName)) {
+            return new ValueSelection<Integer>(getSelectedValue(messageParameters));
+        }
+        else if ("VScroll_TrackBar".equals(eventName)) {
+            return new ValueSelection<Integer>(getSelectedValue(messageParameters));
+        }
+        else if ("HScroll_ScrollBar".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("VScroll_ScrollBar".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("VScrollNC".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("LeftClickSetFocus".equals(eventName)) {
+            return new KeyboardFocusChange();
+        }
+        else if ("LeftClickChangeFocus".equals(eventName)) {
+            return new KeyboardFocusChange();
+        }
+        else if ("KeyDown".equals(eventName)) {
+            return new KeyPressed(getKey(messageParameters));
+        }
+        else if ("KeyUp".equals(eventName)) {
+            return new KeyReleased(getKey(messageParameters));
+        }
+        else if ("SysKeyDown".equals(eventName)) {
+            return new KeyPressed(getKey(messageParameters));
+        }
+        else if ("SysKeyUp".equals(eventName)) {
+            return new KeyReleased(getKey(messageParameters));
+        }
+        else if ("LeftClickCoordinates".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("NCLeftClickCoordinates".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("NCLeftClickCoordinates2".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("LeftClickCoordinatesTargetChanged".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else if ("LeftClickCoordinatesTargetChanged2".equals(eventName)) {
+            return new MouseClick(MouseButtonInteraction.Button.LEFT);
+        }
+        else {
+            throw new IllegalArgumentException("unknown event name: " + eventName);
+        }
+    }
+
+    /**
+     * @param message
+     * @return
+     */
+    private VirtualKey getKey(Map<String, String> messageParameters) {
+        String value = null;
+        
+        if (messageParameters != null) {
+            value = messageParameters.get("key");
+        }
+        
+        if (value == null) {
+            throw new IllegalArgumentException
+                ("no parameter \"key\" provided for key event. Please correct the event " +
+                 "generation rules");
+        }
+        
+        return WindowsVirtualKey.parseVirtualKey(value).getKey();
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param messageParameters
+     * @return
+     */
+    private int getSelectedValue(Map<String, String> messageParameters) {
+        String value = null;
+        
+        if (messageParameters != null) {
+            value = messageParameters.get("scrollPos");
+        }
+        
+        if (value == null) {
+            throw new IllegalArgumentException
+                ("no parameter \"scrollPos\" provided for scroll event. Please correct the event " +
+                 "generation rules");
+        }
+        
+        return Integer.parseInt(value);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCTargetComparator.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/MFCTargetComparator.java	(revision 581)
+++ 	(revision )
@@ -1,412 +1,0 @@
-package de.ugoe.cs.quest.plugin.mfc.eventcore;
-
-import java.io.ByteArrayInputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.apache.commons.collections15.CollectionUtils;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-/**
- * <p>
- * This class implements a comparator for target strings of MFC GUIs. It
- * internally maintains a collection of all targets that have been compared to
- * ensure the transitivity of the equals relation. This memory can always be
- * deleted by calling {@link #reset()}.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- */
-public class MFCTargetComparator {
-
-	/**
-	 * <p>
-	 * If mutable is true, new target strings can be added to the internal
-	 * memory. This leads to a very expensive {@link #compare(String, String)}
-	 * operation.
-	 * </p>
-	 * <p>
-	 * if mutable is set to false, currently possible equal targets are
-	 * pre-computed. This pre-computation is expensive and might take a while.
-	 * In turn, the {@link #compare(String, String)} operation becomes very
-	 * cheap.
-	 * </p>
-	 */
-	private static boolean mutable = true;
-
-	/**
-	 * <p>
-	 * Set of all currently known targets.
-	 * </p>
-	 */
-	private static Set<String> knownTargets = new LinkedHashSet<String>();
-
-	/**
-	 * <p>
-	 * Map that contains for all known target strings all equal target strings.
-	 * Pre-computed when {@link #mutable} is set to false.
-	 * </p>
-	 */
-	private static Map<String, Set<String>> equalTargets;
-
-	/**
-	 * <p>
-	 * Changes the mutability of the comparator. If the mutability is changed
-	 * from true to false, the map {@link #equalTargets} is computed.
-	 * </p>
-	 * 
-	 * @param mutable
-	 *            new mutability of the comparator
-	 */
-	public static void setMutable(boolean mutable) {
-		if (MFCTargetComparator.mutable == true && mutable == false) {
-			equalTargets = new HashMap<String, Set<String>>();
-			for (String target1 : knownTargets) {
-				Set<String> curEqualTargets = new HashSet<String>();
-				for (String target2 : knownTargets) {
-					if (compare(target1, target2)) {
-						curEqualTargets.add(target2);
-					}
-				}
-				equalTargets.put(target1, curEqualTargets);
-			}
-		}
-		MFCTargetComparator.mutable = mutable;
-	}
-
-	/**
-	 * <p>
-	 * Compares to target strings. The strings are equal, if TODO
-	 * <ul>
-	 * <li>the class, resourceId, and modality of all widgets are equal</li>
-	 * <li>either the name or the hashCode of all widgets are equal</li>
-	 * <li>either the name or the hashCode has been observed in one equal
-	 * instance of a widget, for all widgets.</li>
-	 * </ul>
-	 * </p>
-	 * <p>
-	 * All target strings are remembered internally, to be able to test for the
-	 * third property.
-	 * </p>
-	 * 
-	 * @param target1
-	 *            first target string
-	 * @param target2
-	 *            second target string
-	 * @return true, if both targets are equal; false otherwise
-	 */
-	public static boolean compare(String target1, String target2) {
-		boolean result = false;
-		if (mutable) {
-			try {
-				MFCWidget widget1 = null;
-				MFCWidget widget2 = null;
-				if (!"dummy".equals(target1)) {
-					instance.addTarget(target1);
-					knownTargets.add(target1);
-					widget1 = instance.find(target1);
-				}
-				if (!"dummy".equals(target2)) {
-					instance.addTarget(target2);
-					knownTargets.add(target2);
-					widget2 = instance.find(target2);
-				}
-				if (widget1 == null) {
-					return false;
-				}
-				result = (widget1 == widget2);
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-
-		if (!mutable) {
-			Set<String> curEquals = equalTargets.get(target1);
-			if (curEquals != null) {
-				result = curEquals.contains(target2);
-			}
-		}
-
-		return result;
-	}
-
-	/**
-	 * <p>
-	 * Resets the internal memory of targets.
-	 * </p>
-	 */
-	public static void reset() {
-		instance = new MFCTargetComparator();
-	}
-
-	/**
-	 * <p>
-	 * Internal handle to the instance of this class (implemented as
-	 * Singleton!).
-	 * </p>
-	 */
-	private static MFCTargetComparator instance = new MFCTargetComparator();
-
-	/**
-	 * <p>
-	 * Private Constructor. Creates a new instance of the class and prevents
-	 * instantiation from outside of this class.
-	 * </p>
-	 */
-	private MFCTargetComparator() {
-	}
-
-	/**
-	 * <p>
-	 * List of the root widgets found in the target string.
-	 * </p>
-	 */
-	private List<MFCWidget> rootWidgets = new ArrayList<MFCTargetComparator.MFCWidget>();
-
-	/**
-	 * <p>
-	 * Adds a target to the memory.
-	 * </p>
-	 * 
-	 * @param target
-	 *            target to be added
-	 */
-	private void addTarget(String target) throws Exception {
-		if (target != null) {
-			DocumentBuilder documentBuilder = DocumentBuilderFactory
-					.newInstance().newDocumentBuilder();
-			Document doc = documentBuilder.parse(new ByteArrayInputStream(
-					("<dummy>" + target + "</dummy>").getBytes("UTF-8")));
-			doc.getDocumentElement().normalize();
-			NodeList widgets = doc.getElementsByTagName("window");
-
-			MFCWidget parent = null;
-			for (int i = 0; i < widgets.getLength(); i++) {
-				Element currentWidget = (Element) widgets.item(i);
-				parent = addWidget(currentWidget, parent);
-			}
-		}
-	}
-
-	/**
-	 * <p>
-	 * Adds a widget extracted from a target to the memory. The widget is placed
-	 * as a child/parent of other widget according to the GUI hierarchy of the
-	 * application.
-	 * </p>
-	 * <p>
-	 * In case the widget already exists, the existing widget is returned and
-	 * the known targets and hashCodes of the existing widget are updated.
-	 * </p>
-	 * 
-	 * @param widgetString
-	 *            string identifying the widget
-	 * @param parent
-	 *            parent widget; if null, it is a root widget and added to
-	 *            {@link #rootWidgets}
-	 * @return the created widget.
-	 */
-	private MFCWidget addWidget(Element widgetElement, MFCWidget parent) {
-		MFCWidget widget = generateWidget(widgetElement);
-
-		if (parent == null) {
-			int index = rootWidgets.indexOf(widget);
-			if (index >= 0) {
-				widget = rootWidgets.get(index);
-				widget.names.add(widgetElement.getAttribute("name"));
-				widget.hwnds.add(widgetElement.getAttribute("hwnd"));
-			} else {
-				rootWidgets.add(widget);
-			}
-		} else {
-			int index = parent.children.indexOf(widget);
-			if (index >= 0) {
-				widget = parent.children.get(index);
-				widget.names.add(widgetElement.getAttribute("name"));
-				widget.hwnds.add(widgetElement.getAttribute("hwnd"));
-			} else {
-				parent.children.add(widget);
-			}
-		}
-		return widget;
-	}
-
-	/**
-	 * <p>
-	 * Creates a new {@link MFCWidget} from a widget XML element.
-	 * </p>
-	 * 
-	 * @param widgetElement
-	 *            XML element containing information about the widget
-	 * @return created {@link MFCWidget}
-	 */
-	private MFCWidget generateWidget(Element widgetElement) {
-		MFCWidget widget = new MFCWidget();
-		widget.names.add(widgetElement.getAttribute("name"));
-		widget.hwnds.add(widgetElement.getAttribute("hwnd"));
-		widget.widgetClass = widgetElement.getAttribute("class");
-		widget.resourceId = widgetElement.getAttribute("resourceId");
-		widget.modality = widgetElement.getAttribute("isModal");
-		return widget;
-	}
-
-	/**
-	 * <p>
-	 * Tries to find the {@link MFCWidget} that the target string identifies in
-	 * the known GUI hierarchy, by traversing the known widgets starting with
-	 * the {@link #rootWidgets}.
-	 * 
-	 * @param target
-	 *            target string whose widget is searched for
-	 * @return respective {@link MFCWidget} instance if it is found; null
-	 *         otherwise
-	 */
-	private MFCWidget find(String target) throws Exception {
-		MFCWidget widget = null;
-		if (target != null) {
-			DocumentBuilder documentBuilder = DocumentBuilderFactory
-					.newInstance().newDocumentBuilder();
-			Document doc = documentBuilder.parse(new ByteArrayInputStream(
-					("<dummy>" + target + "</dummy>").getBytes("UTF-8")));
-			doc.getDocumentElement().normalize();
-			NodeList widgets = doc.getElementsByTagName("window");
-
-			MFCWidget parent = null;
-			for (int i = 0; i < widgets.getLength(); i++) {
-				Element currentWidget = (Element) widgets.item(i);
-				MFCWidget generatedWidget = generateWidget(currentWidget);
-				if (parent == null) {
-					int index = rootWidgets.indexOf(generatedWidget);
-					if (index >= 0) {
-						parent = rootWidgets.get(index);
-					} else {
-						return null;
-					}
-				} else {
-					int index = parent.children.indexOf(generatedWidget);
-					if (index >= 0) {
-						parent = parent.children.get(index);
-					} else {
-						return null;
-					}
-				}
-			}
-			widget = parent;
-		}
-		return widget;
-	}
-
-	/**
-	 * <p>
-	 * Internal class used to store MFCWidget. The implementation is more like a
-	 * C-style structure, than an actual class.
-	 * </p>
-	 * 
-	 * @author Steffen Herbold
-	 * @version 1.0
-	 */
-	private static class MFCWidget {
-
-		/**
-		 * <p>
-		 * Set of all known name strings of the widget.
-		 * </p>
-		 */
-		Set<String> names = new LinkedHashSet<String>();
-
-		/**
-		 * <p>
-		 * Set of all known hwnds of the widget.
-		 * </p>
-		 */
-		Set<String> hwnds = new LinkedHashSet<String>();
-
-		/**
-		 * <p>
-		 * Class of the widget.
-		 * </p>
-		 */
-		String widgetClass;
-
-		/**
-		 * <p>
-		 * Resource id of the widget.
-		 * </p>
-		 */
-		String resourceId;
-
-		/**
-		 * <p>
-		 * Modality of the widget.
-		 * </p>
-		 */
-		String modality;
-
-		/**
-		 * <p>
-		 * Pre-computed hash code of the widget.
-		 * </p>
-		 */
-		int hashCode = 0;
-
-		/**
-		 * <p>
-		 * List of children of the widget.
-		 * </p>
-		 */
-		List<MFCWidget> children = new ArrayList<MFCTargetComparator.MFCWidget>();
-
-		/**
-		 * <p>
-		 * Two widgets are equal, if {@link #widgetClass}, {@link #resourceId},
-		 * and {@link #modality} are equal and the intersection of either the
-		 * {@link #hwnds}, the {@link #names}, or both of them is not empty.
-		 * </p>
-		 * 
-		 * @see java.lang.Object#equals(java.lang.Object)
-		 */
-		@Override
-		public boolean equals(Object obj) {
-			if (obj instanceof MFCWidget) {
-				MFCWidget other = (MFCWidget) obj;
-				boolean titleEqual = CollectionUtils.containsAny(names,
-						other.names);
-				boolean hashEqual = CollectionUtils.containsAny(hwnds,
-						other.hwnds);
-
-				return widgetClass.equals(other.widgetClass)
-						&& resourceId.equals(other.resourceId)
-						&& modality.equals(other.modality)
-						&& (titleEqual || hashEqual);
-			}
-			return false;
-		}
-
-		/*
-		 * (non-Javadoc)
-		 * 
-		 * @see java.lang.Object#hashCode()
-		 */
-		@Override
-		public int hashCode() {
-			if (hashCode == 0) {
-				int multiplier = 17;
-				hashCode = multiplier * hashCode + widgetClass.hashCode();
-				hashCode = multiplier * hashCode + resourceId.hashCode();
-				hashCode = multiplier * hashCode + modality.hashCode();
-			}
-			return hashCode;
-		}
-	}
-}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/ReplayWindowsMessage.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/ReplayWindowsMessage.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/ReplayWindowsMessage.java	(revision 619)
@@ -0,0 +1,275 @@
+
+package de.ugoe.cs.quest.plugin.mfc.eventcore;
+
+import de.ugoe.cs.quest.IReplayDecorator;
+import de.ugoe.cs.quest.eventcore.IReplayable;
+import de.ugoe.cs.quest.plugin.mfc.MFCReplayDecorator;
+import de.ugoe.cs.util.StringTools;
+
+/**
+ * <p>
+ * Contains all informations about a windows message, i.e., all parameters that are read when a
+ * windows message is parsed as well as its target, hwnd, etc.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ * 
+ */
+public class ReplayWindowsMessage extends WindowsMessage implements IReplayable {
+
+    /**
+     * <p>
+     * Id for object serialization.
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * If the LPARAM contains a HWND, this string stores the target of the HWND.
+     * </p>
+     */
+    private String LPARAMasWindowDesc = null;
+
+    /**
+     * <p>
+     * If the WPARAM contains a HWND, this string stores the target of the HWND.
+     * </p>
+     */
+    private String WPARAMasWindowDesc = null;
+
+    /**
+     * <p>
+     * Delay after sending the messages during a replay. Default: 0
+     * </p>
+     */
+    private int delay = 0;
+
+    /**
+     * <p>
+     * Constructor. Creates a new message with a given message type.
+     * </p>
+     * 
+     * @param type
+     *            type of the message
+     * @param currentMessageParameters 
+     * @param target 
+     */
+    public ReplayWindowsMessage(WindowsMessage replayedMessage)
+    {
+        super(replayedMessage.getType(),
+              replayedMessage.getTarget(),
+              replayedMessage.getParameters());
+    }
+
+    /**
+     * <p>
+     * Constructor. Creates a new message with a given message type.
+     * </p>
+     * 
+     * @param type
+     *            type of the message
+     */
+    public ReplayWindowsMessage(WindowsMessageType type)
+    {
+        super(type);
+    }
+
+    /**
+     * <p>
+     * Two {@link ReplayWindowsMessage} are equal, if their {@link #type}, {@link #xmlWindowDescription},
+     * and {@link #params} are equal.
+     * </p>
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        boolean isEqual = false;
+        if (other instanceof ReplayWindowsMessage) {
+            isEqual = super.equals(other);
+        }
+        return isEqual;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    /**
+     * <p>
+     * Returns a string representation of the message of the form "msg[target=HWND;type=TYPE]".
+     * </p>
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "msg[target=" + getParameter("window.hwnd") + ";type=" + type + "]";
+    }
+
+    /**
+     * <p>
+     * Sets the LPARAM of a message.
+     * </p>
+     * 
+     * @param paramValue
+     *            value of the LPARAM
+     */
+    public void setLPARAM(long paramValue) {
+        super.addParameter("LPARAM", paramValue);
+    }
+
+    /**
+     * <p>
+     * Sets the WPARAM of a message.
+     * </p>
+     * 
+     * @param paramValue
+     *            value of the WPARAM
+     */
+    public void setWPARAM(long paramValue) {
+        super.addParameter("WPARAM", paramValue);
+    }
+
+    /**
+     * <p>
+     * If the LPARAM contains a HWND, this function can be used to set a target string to identify
+     * the HWND at run-time.
+     * </p>
+     * 
+     * @param windowDesc
+     *            target string
+     */
+    public void setLPARAMasWindowDesc(String windowDesc) {
+        LPARAMasWindowDesc = windowDesc;
+    }
+
+    /**
+     * <p>
+     * If the WPARAM contains a HWND, this function can be used to set a target string to identify
+     * the HWND at run-time.
+     * </p>
+     * 
+     * @param windowDesc
+     *            target string
+     */
+    public void setWPARAMasWindowDesc(String windowDesc) {
+        WPARAMasWindowDesc = windowDesc;
+    }
+
+    /**
+     * <p>
+     * If the LPARAM contains a HWND and the target string for the HWND is set, this function
+     * returns the target string. Otherwise, {@code null} is returned.
+     * </p>
+     * 
+     * @return target string if available; {@code null} otherwise
+     */
+    public String getLPARAMasWindowDesc() {
+        return LPARAMasWindowDesc;
+    }
+
+    /**
+     * <p>
+     * If the WPARAM contains a HWND and the target string for the HWND is set, this function
+     * returns the target string. Otherwise, {@code null} is returned.
+     * </p>
+     * 
+     * @return target string if available; {@code null} otherwise
+     */
+    public String getWPARAMasWindowDesc() {
+        return WPARAMasWindowDesc;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param termValue
+     */
+    public void setTargetXML(String targetXML) {
+        this.targetXML = targetXML;
+    }
+
+    /**
+     * <p>
+     * Returns the delay after this message during replays.
+     * </p>
+     * 
+     * @return delay after this message
+     */
+    public int getDelay() {
+        return delay;
+    }
+
+    /**
+     * <p>
+     * Sets the delay after this message during replays.
+     * </p>
+     * 
+     * @param delay
+     *            delay after this message
+     */
+    public void setDelay(int delay) {
+        this.delay = delay;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.eventcore.IReplayable#getReplay()
+     */
+    @Override
+    public String getReplay() {
+        StringBuilder currentMsgStr = new StringBuilder(400);
+        currentMsgStr.append("  <msg type=\"" + type.getNumber() + "\" ");
+        currentMsgStr.append("LPARAM=\"" + super.getLPARAM() + "\" ");
+        currentMsgStr.append("WPARAM=\"" + super.getWPARAM() + "\" ");
+        currentMsgStr.append("delay=\"" + delay + "\">");
+        if (LPARAMasWindowDesc != null) {
+            currentMsgStr.append(StringTools.ENDLINE);
+            currentMsgStr.append("   <LPARAM>");
+            currentMsgStr.append(StringTools.ENDLINE);
+            currentMsgStr.append(LPARAMasWindowDesc);
+            currentMsgStr.append(StringTools.ENDLINE);
+            currentMsgStr.append("</LPARAM>");
+        }
+        if (WPARAMasWindowDesc != null) {
+            currentMsgStr.append(StringTools.ENDLINE);
+            currentMsgStr.append("   <WPARAM>");
+            currentMsgStr.append(StringTools.ENDLINE);
+            currentMsgStr.append(WPARAMasWindowDesc);
+            currentMsgStr.append(StringTools.ENDLINE);
+            currentMsgStr.append("   </WPARAM>");
+        }
+        currentMsgStr.append(StringTools.ENDLINE);
+        currentMsgStr.append(super.getTargetXML());
+        currentMsgStr.append(StringTools.ENDLINE);
+        currentMsgStr.append("  </msg>");
+        currentMsgStr.append(StringTools.ENDLINE);
+        return currentMsgStr.toString();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.eventcore.IReplayable#getDecorator()
+     */
+    @Override
+    public IReplayDecorator getDecorator() {
+        return MFCReplayDecorator.getInstance();
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowTree.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowTree.java	(revision 581)
+++ 	(revision )
@@ -1,188 +1,0 @@
-package de.ugoe.cs.quest.plugin.mfc.eventcore;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- * <p>
- * This class provides an the interfaces for window trees.
- * </p>
- * <p>
- * The window tree represents the hierarchical structure of the windows
- * "as it is" currently during a session. It may change during the session due
- * to creation and destruction of windows.
- * </p>
- * <p>
- * The class is implemented as a singleton. The rational behind implementing
- * this class as a singleton is to ease the access of all class that may request
- * information about the windows during the parsing of a session. As the tree
- * may change during the session, it does not make sense to preserve it after a
- * session. Thus, it can just be deleted. Therefore, as long as only one session
- * is parsed at a time, a single instance is sufficient.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- */
-public class WindowTree {
-
-	/**
-	 * <p>
-	 * Handle to the window instance.
-	 * </p>
-	 */
-	private static WindowTree theInstance = null;
-
-	/**
-	 * <p>
-	 * Maintains a set of all the target strings of all widgets that were at
-	 * some point part of the window tree.
-	 * </p>
-	 */
-	private SortedSet<String> targets;
-
-	/**
-	 * <p>
-	 * Obtain a handle to the window instance.
-	 * </p>
-	 * 
-	 * @return instance of the window tree
-	 */
-	public static WindowTree getInstance() {
-		if (theInstance == null) {
-			theInstance = new WindowTree();
-		}
-		return theInstance;
-	}
-
-	/**
-	 * <p>
-	 * Resets the tree. Should be used between sessions.
-	 * </p>
-	 */
-	public static void resetTree() {
-		theInstance = null;
-	}
-
-	/**
-	 * <p>
-	 * Map of all windows that are part of the tree for efficient searching. The
-	 * keys of the map are the hwnd's of the windows.
-	 * </p>
-	 */
-	private Map<Integer, WindowTreeNode> nodes;
-
-	/**
-	 * <p>
-	 * Creates a new WindowTree.
-	 * </p>
-	 * <p>
-	 * Private, as the class is a singleton.
-	 * </p>
-	 */
-	private WindowTree() {
-		nodes = new HashMap<Integer, WindowTreeNode>();
-		targets = new TreeSet<String>();
-	}
-
-	/**
-	 * <p>
-	 * Adds a new window to the tree.
-	 * </p>
-	 * 
-	 * @param parentHwnd
-	 *            hwnd of the parent window
-	 * @param childHwnd
-	 *            hwnd of the window to be created
-	 * @param childWindowName
-	 *            resource id of the window to be created
-	 * @param resourceId
-	 *            resource id of the window to be created
-	 * @param className
-	 *            class name of the window to be created
-	 */
-	public void add(int parentHwnd, int childHwnd, String childWindowName,
-			int resourceId, String className, boolean isModal) {
-		WindowTreeNode parent = nodes.get(parentHwnd);
-		WindowTreeNode child = nodes.get(childHwnd);
-		if (child == null) {
-			if (parent != null) {
-				child = parent.addChild(childHwnd, childWindowName, resourceId,
-						className, isModal);
-			} else {
-				child = new WindowTreeNode(childHwnd, null, childWindowName,
-						resourceId, className, isModal);
-			}
-			nodes.put(childHwnd, child);
-			targets.add(child.xmlRepresentation());
-		}
-	}
-
-	/**
-	 * <p>
-	 * Removes a window (defined by its hwnd) from the tree. All children of the
-	 * window will be removed recursively.
-	 * </p>
-	 * 
-	 * @param hwnd
-	 *            hwnd of the window to be removed
-	 * @return number of windows that were removed
-	 */
-	public int remove(int hwnd) {
-		int removedCounter = 0;
-		WindowTreeNode node = nodes.get(hwnd);
-		if (node != null) {
-			List<WindowTreeNode> nodesToBeRemoved = node.remove();
-			for (int i = 0; i < nodesToBeRemoved.size(); i++) {
-				WindowTreeNode nodeToBeRemoved = nodesToBeRemoved.get(i);
-				nodesToBeRemoved.addAll(nodeToBeRemoved.getChildren());
-				nodes.remove(nodeToBeRemoved.getHwnd());
-				removedCounter++;
-			}
-			nodes.remove(hwnd);
-			removedCounter++;
-		}
-		return removedCounter;
-	}
-
-	/**
-	 * <p>
-	 * Searches the tree for a window with the specified hwnd and returns its
-	 * {@link WindowTreeNode}.
-	 * </p>
-	 * 
-	 * @param hwnd
-	 *            hwnd that is looked for
-	 * @return {@link WindowTreeNode} of the window with the given hwnd if
-	 *         found, null otherwise
-	 */
-	public WindowTreeNode find(int hwnd) {
-		return nodes.get(hwnd);
-	}
-
-	/**
-	 * <p>
-	 * Returns the number of nodes contained in the WindowTree.
-	 * </p>
-	 * 
-	 * @return number of nodes
-	 */
-	public int size() {
-		return nodes.size();
-	}
-
-	/**
-	 * <p>
-	 * Returns a sorted set of all targets that existed any time in the window
-	 * tree.
-	 * </p>
-	 * 
-	 * @return set of targets
-	 */
-	public SortedSet<String> getTargets() {
-		return targets;
-	}
-}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowTreeNode.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowTreeNode.java	(revision 581)
+++ 	(revision )
@@ -1,292 +1,0 @@
-package de.ugoe.cs.quest.plugin.mfc.eventcore;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import de.ugoe.cs.util.StringTools;
-
-/**
- * <p>
- * This class implements a node in the {@link WindowTree} that is maintained
- * during parsing a session.
- * </p>
- * <p>
- * The window tree is structure that contains the hierarchy of the windows of a
- * application as well as basic information about each window: the hwnd; its
- * name; its resource id; its class name.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- */
-public class WindowTreeNode {
-
-	/**
-	 * <p>
-	 * Name of the window. May change over time.
-	 * </p>
-	 */
-	private String windowName;
-
-	/**
-	 * <p>
-	 * Handle of the window. Used as unique identifier during its existence.
-	 * </p>
-	 */
-	private final int hwnd;
-
-	/**
-	 * <p>
-	 * Resource id of the window.
-	 * </p>
-	 */
-	private final int resourceId;
-
-	/**
-	 * <p>
-	 * Class name of the window.
-	 * </p>
-	 */
-	private final String className;
-
-	/**
-	 * <p>
-	 * True, if the window is modal.
-	 * </p>
-	 */
-	private final boolean isModal;
-
-	/**
-	 * <p>
-	 * Parent of the window. <code>null</code> if the window has no parent.
-	 * </p>
-	 */
-	private WindowTreeNode parent;
-
-	/**
-	 * <p>
-	 * List of the windows children. May be empty.
-	 * </p>
-	 */
-	private List<WindowTreeNode> children;
-
-	/**
-	 * <p>
-	 * Creates a new WindowTreeNode.
-	 * </p>
-	 * <p>
-	 * The constructor is protected WindowTreeNode may only be created from the
-	 * WindowTree.
-	 * </p>
-	 * 
-	 * @param hwnd
-	 *            hwnd of the window
-	 * @param parent
-	 *            reference to the parent's WindowTreeNode
-	 * @param windowName
-	 *            name of the window
-	 * @param resourceId
-	 *            resource id of the window
-	 * @param className
-	 *            class name of the window
-	 * @param isModal
-	 *            modality of the window
-	 */
-	protected WindowTreeNode(int hwnd, WindowTreeNode parent,
-			String windowName, int resourceId, String className, boolean isModal) {
-		this.hwnd = hwnd;
-		this.parent = parent;
-		this.windowName = windowName;
-		this.resourceId = resourceId;
-		this.className = className;
-		this.isModal = isModal;
-		children = new ArrayList<WindowTreeNode>();
-	}
-
-	/**
-	 * <p>
-	 * Returns a reference to the WindowTreeNode of the parent.
-	 * </p>
-	 * 
-	 * @return WindowTreeNode of the parent
-	 */
-	public WindowTreeNode getParent() {
-		return parent;
-	}
-
-	/**
-	 * <p>
-	 * Returns the list of the windows children.
-	 * </p>
-	 * 
-	 * @return list of the windows children
-	 */
-	public List<WindowTreeNode> getChildren() {
-		return children;
-	}
-
-	/**
-	 * <p>
-	 * Returns the name of the window.
-	 * </p>
-	 * 
-	 * @return name of the window
-	 */
-	public String getName() {
-		return windowName;
-	}
-
-	/**
-	 * <p>
-	 * Returns the hwnd of the window.
-	 * </p>
-	 * 
-	 * @return hwnd of the window
-	 */
-	public int getHwnd() {
-		return hwnd;
-	}
-
-	/**
-	 * <p>
-	 * Returns the resource id of the window.
-	 * </p>
-	 * 
-	 * @return resource id of the window
-	 */
-	public int getResourceId() {
-		return resourceId;
-	}
-
-	/**
-	 * <p>
-	 * Returns the class name of the window.
-	 * </p>
-	 * 
-	 * @return class name of the window
-	 */
-	public String getClassName() {
-		return className;
-	}
-
-	/**
-	 * <p>
-	 * Sets the name of the window.
-	 * </p>
-	 * 
-	 * @param text
-	 *            new name of the window
-	 */
-	public void setName(String text) {
-		windowName = text;
-	}
-
-	/**
-	 * <p>
-	 * Removes a the window and all its children from the {@link WindowTree}.
-	 * </p>
-	 * 
-	 * @return list of the children of the window for further clean up.
-	 */
-	public List<WindowTreeNode> remove() {
-		if (parent != null) {
-			parent.removeChild(this);
-		}
-		return children;
-	}
-
-	/**
-	 * <p>
-	 * Removes a child window.
-	 * </p>
-	 * 
-	 * @param child
-	 *            reference to the child window to be removed
-	 */
-	public void removeChild(WindowTreeNode child) {
-		children.remove(child);
-	}
-
-	/**
-	 * <p>
-	 * Adds a new child window and creates WindowTreeNode for it.
-	 * </p>
-	 * 
-	 * @param childHwnd
-	 *            hwnd of the child window
-	 * @param childWindowName
-	 *            name of the child window
-	 * @param resourceId
-	 *            resource id of the child window
-	 * @param className
-	 *            class name of the child window
-	 * @param isModal
-	 *            modality of the child window
-	 * @return reference to the WindowTreeNode created for the child window
-	 */
-	public WindowTreeNode addChild(int childHwnd, String childWindowName,
-			int resourceId, String className, boolean isModal) {
-		WindowTreeNode child = new WindowTreeNode(childHwnd, this,
-				childWindowName, resourceId, className, isModal);
-		children.add(child);
-		return child;
-	}
-
-	/**
-	 * <p>
-	 * Returns a string identfier of the window:<br>
-	 * {@code [resourceId;"windowName";"className";modality]}
-	 * </p>
-	 * 
-	 * @return identifier string of the window
-	 */
-	@Override
-	public String toString() {
-		return "[" + resourceId + ";\"" + windowName + "\";\"" + className
-				+ "\";" + isModal + "]";
-	}
-
-	/**
-	 * <p>
-	 * Returns an XML representation of the window, including its parents. It is
-	 * defined as follows:<br>
-	 * <code>
-	 * parent#xmlRepresentation()<br>
-	 * &lt;window name="this.windowname" class="this.className" resourceId="this.resourceId" isModal="this.isModel"/&gt;
-	 * </code>
-	 * </p>
-	 * 
-	 * @return xml representation of the window
-	 */
-	public String xmlRepresentation() {
-		String xmlString = "";
-		if (parent != null) {
-			xmlString = parent.xmlRepresentation();
-		}
-		xmlString += "<window name=\""
-				+ StringTools.xmlEntityReplacement(windowName) + "\" class=\""
-				+ StringTools.xmlEntityReplacement(className)
-				+ "\" resourceId=\"" + resourceId + "\" isModal=\"" + isModal
-				+ "\" hwnd=\"" + hwnd + "\""
-				+ "/>";
-		return xmlString;
-	}
-
-	/**
-	 * <p>
-	 * Returns the names of the parents and itself separated by dots, e.g.,
-	 * "GrandParent.Parent.windowName"
-	 * </p>
-	 * 
-	 * @return names of the parents separated by dots
-	 */
-	public String getParentNames() {
-		String parentNames = "";
-		if (parent != null) {
-			parentNames = parent.getParentNames() + ".";
-		}
-		parentNames += windowName;
-		return parentNames;
-	}
-
-}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsEvent.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsEvent.java	(revision 581)
+++ 	(revision )
@@ -1,88 +1,0 @@
-package de.ugoe.cs.quest.plugin.mfc.eventcore;
-
-import java.io.ByteArrayInputStream;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-import de.ugoe.cs.quest.eventcore.Event;
-
-
-/**
- * <p>
- * Convenience class for working with Windows MFC events.
- * </p>
- * 
- * @author Steffen Herbold
- * @version 1.0
- * @deprecated This class is deprecated and only kept for now for documentation - some features still need to be extracted and reconstructed elsewhere
- */
-public class WindowsEvent extends Event {
-
-	/**
-	 * <p>
-	 * Id for object serialization.
-	 * </p>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * <p>
-	 * Constructor. Creates a new WindowEvent.
-	 * </p>
-	 * 
-	 * @see de.ugoe.cs.quest.eventcore.Event#Event(String)
-	 * @param type
-	 *            type of the event.
-	 */
-	public WindowsEvent(String type) {
-		super(new MFCEventType("foo"));
-	}
-
-	//@Override
-	protected boolean targetEquals(String otherTarget) {
-		return MFCTargetComparator.compare(target.toString(), otherTarget);
-	}
-	
-	int targetHash = 0;
-	
-	//@Override
-	protected int targetHashCode() {
-		if( targetHash==0 ) {
-			int multiplier = 17;
-			if (target != null) {
-				Document doc;
-				try {
-					DocumentBuilder documentBuilder = DocumentBuilderFactory
-							.newInstance().newDocumentBuilder();
-					doc = documentBuilder.parse(new ByteArrayInputStream(
-							("<dummy>" + target + "</dummy>").getBytes("UTF-8")));
-				} catch (Exception e) {
-					e.printStackTrace();
-					return 0;
-				}
-				doc.getDocumentElement().normalize();
-				NodeList widgets = doc.getElementsByTagName("window");
-
-				for (int i = 0; i < widgets.getLength(); i++) {
-					Element currentWidget = (Element) widgets.item(i);
-					targetHash = targetHash* multiplier + widgetHashCode(currentWidget);
-				}
-			}
-		}
-		return targetHash;
-	}
-	
-	private int widgetHashCode(Element currentWidget) {
-		int hashCode = 0;
-		int multiplier = 41;
-		hashCode = hashCode * multiplier + currentWidget.getAttribute("class").hashCode();
-		hashCode = hashCode * multiplier + currentWidget.getAttribute("resourceId").hashCode();
-		hashCode = hashCode * multiplier + currentWidget.getAttribute("isModal").hashCode();
-		return hashCode;
-	}
-}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsMessage.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsMessage.java	(revision 581)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsMessage.java	(revision 619)
@@ -1,17 +1,14 @@
+
 package de.ugoe.cs.quest.plugin.mfc.eventcore;
 
-import java.security.InvalidParameterException;
 import java.util.HashMap;
 import java.util.Map;
 
-import de.ugoe.cs.quest.IReplayDecorator;
-import de.ugoe.cs.quest.eventcore.IReplayable;
-import de.ugoe.cs.quest.plugin.mfc.MFCReplayDecorator;
-import de.ugoe.cs.util.StringTools;
+import de.ugoe.cs.quest.plugin.mfc.guimodel.MFCGUIElement;
 
 /**
  * <p>
- * Contains all informations about a windows message, i.e., all parameters that
- * are read when a windows message is parsed as well as its target, hwnd, etc.
+ * Contains all informations about a windows message, i.e., all parameters that are read when a
+ * windows message is parsed as well as its target, hwnd, etc.
  * </p>
  * 
@@ -20,501 +17,258 @@
  * 
  */
-public class WindowsMessage implements IReplayable {
-
-	/**
-	 * <p>
-	 * Id for object serialization.
-	 * </p>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * <p>
-	 * Type of the message.
-	 * </p>
-	 */
-	final int type;
-
-	/**
-	 * <p>
-	 * Window class of the message target. Default: ""
-	 * </p>
-	 */
-	private String windowClass = "";
-
-	/**
-	 * <p>
-	 * Resource Id of the message target. Default: 0
-	 * </p>
-	 */
-	private int resourceId = 0;
-
-	/**
-	 * <p>
-	 * XML representation of the message target.
-	 * </p>
-	 */
-	private String xmlWindowDescription = "";
-
-	/**
-	 * <p>
-	 * String that contains the names of all parent widgets and itself, separated by dots,
-	 * e.g., "GrandParent.Parent.self".
-	 * </p>
-	 */
-	private String parentNames = null;
-
-	/**
-	 * <p>
-	 * String that contains the window class of the parent widget.
-	 * </p>
-	 */
-	private String parentClass = null;
-
-	/**
-	 * <p>
-	 * LPARAM of the message. Default: 0
-	 * </p>
-	 */
-	private long LPARAM = 0;
-
-	/**
-	 * <p>
-	 * WPARAM of the message. Default: 0
-	 * </p>
-	 */
-	private long WPARAM = 0;
-
-	/**
-	 * <p>
-	 * If the LPARAM contains a HWND, this string stores the target of the HWND.
-	 * </p>
-	 */
-	private String LPARAMasWindowDesc = null;
-
-	/**
-	 * <p>
-	 * If the WPARAM contains a HWND, this string stores the target of the HWND.
-	 * </p>
-	 */
-	private String WPARAMasWindowDesc = null;
-
-	/**
-	 * <p>
-	 * Delay after sending the messages during a replay. Default: 0
-	 * </p>
-	 */
-	private int delay = 0;
-
-	/**
-	 * <p>
-	 * A map of all parameters, associated with the message, created during the
-	 * parsing of messages from the logs {@code param}-nodes.
-	 * </p>
-	 */
-	private Map<String, String> params = new HashMap<String, String>();
-
-	/**
-	 * <p>
-	 * Constructor. Creates a new message with a given message type.
-	 * </p>
-	 * 
-	 * @param type
-	 *            type of the message
-	 */
-	public WindowsMessage(int type) {
-		this.type = type;
-	}
-
-	/**
-	 * <p>
-	 * Adds a parameter to the message.
-	 * </p>
-	 * 
-	 * @param type
-	 *            type descriptor of the parameter
-	 * @param value
-	 *            value of the parameter
-	 */
-	public void addParameter(String type, String value) {
-		params.put(type, value);
-		if (type.equals("LPARAM")) {
-			LPARAM = Long.parseLong(value);
-		} else if (type.equals("WPARAM")) {
-			WPARAM = Long.parseLong(value);
-		}
-	}
-
-	/**
-	 * <p>
-	 * Returns the type of the message.
-	 * </p>
-	 * 
-	 * @return type of the message
-	 */
-	public int getType() {
-		return type;
-	}
-
-	/**
-	 * <p>
-	 * Returns the value of a parameter, given its type. If the parameter is not
-	 * found, {@code null} is returned.
-	 * </p>
-	 * 
-	 * @param type
-	 *            type of the parameter
-	 * @return value of the parameter
-	 */
-	public String getParameter(String type) {
-		return params.get(type);
-	}
-
-	/**
-	 * <p>
-	 * Returns the window class of the message target.
-	 * </p>
-	 * 
-	 * @return window class of the message target
-	 */
-	public String getWindowClass() {
-		return windowClass;
-	}
-
-	/**
-	 * <p>
-	 * Returns the HWND the message is addressed to.
-	 * </p>
-	 * 
-	 * @return HWND the message is addressed to
-	 */
-	public int getHwnd() {
-		int hwnd = -1;
-		String hwndString = getParameter("window.hwnd"); // possible, as
-															// "window.hwnd" is
-															// mandatory
-		if (hwndString != null) {
-			hwnd = Integer.parseInt(hwndString);
-		}
-		return hwnd;
-	}
-
-	/**
-	 * <p>
-	 * Returns the resource Id of the message target.
-	 * </p>
-	 * 
-	 * @return resource Id of the message target
-	 */
-	public int getWindowResourceId() {
-		return resourceId;
-	}
-
-	/**
-	 * <p>
-	 * Two {@link WindowsMessage} are equal, if their {@link #type},
-	 * {@link #xmlWindowDescription}, and {@link #params} are equal.
-	 * </p>
-	 * 
-	 * @see java.lang.Object#equals(java.lang.Object)
-	 */
-	@Override
-	public boolean equals(Object other) {
-		if (other == this) {
-			return true;
-		}
-		boolean isEqual = false;
-		if (other instanceof WindowsMessage) {
-			isEqual = ((WindowsMessage) other).type == this.type
-					&& ((WindowsMessage) other).xmlWindowDescription
-							.equals(this.xmlWindowDescription)
-					&& ((WindowsMessage) other).params.equals(this.params);
-		}
-		return isEqual;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see java.lang.Object#hashCode()
-	 */
-	@Override
-	public int hashCode() {
-		int multiplier = 17;
-		int hash = 42;
-
-		hash = multiplier * hash + type;
-		hash = multiplier * hash + xmlWindowDescription.hashCode();
-		hash = multiplier * hash + params.hashCode();
-
-		return hash;
-	}
-
-	/**
-	 * <p>
-	 * Returns a string representation of the message of the form
-	 * "msg[target=HWND;type=TYPE]".
-	 * </p>
-	 * 
-	 * @see java.lang.Object#toString()
-	 */
-	@Override
-	public String toString() {
-		return "msg[target=" + getParameter("window.hwnd") + ";type=" + type
-				+ "]";
-	}
-
-	/**
-	 * <p>
-	 * Retrieves the target string of a message from a given {@link WindowTree}
-	 * through looking up the HWND the message is addressed to in the window
-	 * tree.
-	 * </p>
-	 * 
-	 * @param windowTree
-	 *            {@link WindowTree} from which the target is extracted
-	 * @throws InvalidParameterException
-	 *             thrown if HWND is not contained in windowTree
-	 */
-	public void setTarget(WindowTree windowTree)
-			throws InvalidParameterException {
-		int hwnd = Integer.parseInt(getParameter("window.hwnd"));
-		WindowTreeNode node = windowTree.find(hwnd);
-		if (node == null) {
-			throw new InvalidParameterException("No window with HWND " + hwnd
-					+ " found in window tree!");
-		} else {
-			windowClass = node.getClassName();
-			resourceId = node.getResourceId();
-			xmlWindowDescription = node.xmlRepresentation();
-			parentNames = node.getParentNames();
-			WindowTreeNode parent = node.getParent();
-			if (parent == null) {
-				parentClass = "";
-			} else {
-				parentClass = parent.getClassName();
-			}
-		}
-	}
-
-	/**
-	 * <p>
-	 * Sets the LPARAM of a message.
-	 * </p>
-	 * 
-	 * @param paramValue
-	 *            value of the LPARAM
-	 */
-	public void setLPARAM(long paramValue) {
-		LPARAM = paramValue;
-	}
-
-	/**
-	 * <p>
-	 * Sets the WPARAM of a message.
-	 * </p>
-	 * 
-	 * @param paramValue
-	 *            value of the WPARAM
-	 */
-	public void setWPARAM(long paramValue) {
-		WPARAM = paramValue;
-	}
-
-	/**
-	 * <p>
-	 * Returns the LPARAM of a message.
-	 * </p>
-	 * 
-	 * @return LPARAM of the message
-	 */
-	public long getLPARAM() {
-		return LPARAM;
-	}
-
-	/**
-	 * <p>
-	 * Returns the WPARAM of a message.
-	 * </p>
-	 * 
-	 * @return WPARAM of the message
-	 */
-	public long getWPARAM() {
-		return WPARAM;
-	}
-
-	/**
-	 * <p>
-	 * If the LPARAM contains a HWND, this function can be used to set a target
-	 * string to identify the HWND at run-time.
-	 * </p>
-	 * 
-	 * @param windowDesc
-	 *            target string
-	 */
-	public void setLPARAMasWindowDesc(String windowDesc) {
-		LPARAMasWindowDesc = windowDesc;
-	}
-
-	/**
-	 * <p>
-	 * If the WPARAM contains a HWND, this function can be used to set a target
-	 * string to identify the HWND at run-time.
-	 * </p>
-	 * 
-	 * @param windowDesc
-	 *            target string
-	 */
-	public void setWPARAMasWindowDesc(String windowDesc) {
-		WPARAMasWindowDesc = windowDesc;
-	}
-
-	/**
-	 * <p>
-	 * If the LPARAM contains a HWND and the target string for the HWND is set,
-	 * this function returns the target string. Otherwise, {@code null} is
-	 * returned.
-	 * </p>
-	 * 
-	 * @return target string if available; {@code null} otherwise
-	 */
-	public String getLPARAMasWindowDesc() {
-		return LPARAMasWindowDesc;
-	}
-
-	/**
-	 * <p>
-	 * If the WPARAM contains a HWND and the target string for the HWND is set,
-	 * this function returns the target string. Otherwise, {@code null} is
-	 * returned.
-	 * </p>
-	 * 
-	 * @return target string if available; {@code null} otherwise
-	 */
-	public String getWPARAMasWindowDesc() {
-		return WPARAMasWindowDesc;
-	}
-
-	/**
-	 * <p>
-	 * Returns the target string of the message.
-	 * </p>
-	 * 
-	 * @return target string of the message
-	 */
-	public String getXmlWindowDescription() {
-		return xmlWindowDescription;
-	}
-
-	/**
-	 * <p>
-	 * Sets the target string manually.
-	 * </p>
-	 * 
-	 * @param xmlWindowDescription
-	 *            target string
-	 */
-	public void setXmlWindowDescription(String xmlWindowDescription) {
-		this.xmlWindowDescription = xmlWindowDescription;
-	}
-
-	/**
-	 * <p>
-	 * Returns the delay after this message during replays.
-	 * </p>
-	 * 
-	 * @return delay after this message
-	 */
-	public int getDelay() {
-		return delay;
-	}
-
-	/**
-	 * <p>
-	 * Sets the delay after this message during replays.
-	 * </p>
-	 * 
-	 * @param delay
-	 *            delay after this message
-	 */
-	public void setDelay(int delay) {
-		this.delay = delay;
-	}
-
-	/**
-	 * <p>
-	 * Returns the parent names separated by dots, e.g., "GrandParent.Parent".
-	 * </p>
-	 * 
-	 * @return names of the parents
-	 */
-	public String getParentNames() {
-		return parentNames;
-	}
-
-	/**
-	 * <p>
-	 * Returns the window class of the parent.
-	 * </p>
-	 * 
-	 * @return window classes of the parents
-	 */
-	public String getParentClass() {
-		return parentClass;
-	}
-
-	/**
-	 * <p>
-	 * Returns the number of parameters stored together with this message.
-	 * </p>
-	 * 
-	 * @return number of parameters stored with this message
-	 */
-	public int getNumParams() {
-		return params.size();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see de.ugoe.cs.quest.eventcore.IReplayable#getReplay()
-	 */
-	@Override
-	public String getReplay() {
-		StringBuilder currentMsgStr = new StringBuilder(400);
-		currentMsgStr.append("  <msg type=\"" + type + "\" ");
-		currentMsgStr.append("LPARAM=\"" + LPARAM + "\" ");
-		currentMsgStr.append("WPARAM=\"" + WPARAM + "\" ");
-		currentMsgStr.append("delay=\"" + delay + "\">");
-		if (LPARAMasWindowDesc != null) {
-			currentMsgStr.append(StringTools.ENDLINE);
-			currentMsgStr.append("   <LPARAM>");
-			currentMsgStr.append(StringTools.ENDLINE);
-			currentMsgStr.append(LPARAMasWindowDesc);
-			currentMsgStr.append(StringTools.ENDLINE);
-			currentMsgStr.append("</LPARAM>");
-		}
-		if (WPARAMasWindowDesc != null) {
-			currentMsgStr.append(StringTools.ENDLINE);
-			currentMsgStr.append("   <WPARAM>");
-			currentMsgStr.append(StringTools.ENDLINE);
-			currentMsgStr.append(WPARAMasWindowDesc);
-			currentMsgStr.append(StringTools.ENDLINE);
-			currentMsgStr.append("   </WPARAM>");
-		}
-		currentMsgStr.append(StringTools.ENDLINE);
-		currentMsgStr.append(xmlWindowDescription);
-		currentMsgStr.append(StringTools.ENDLINE);
-		currentMsgStr.append("  </msg>");
-		currentMsgStr.append(StringTools.ENDLINE);
-		return currentMsgStr.toString();
-	}
-
-    /* (non-Javadoc)
-     * @see de.ugoe.cs.quest.eventcore.IReplayable#getDecorator()
+public class WindowsMessage {
+
+    /**
+     * <p>
+     * Type of the message.
+     * </p>
+     */
+    final WindowsMessageType type;
+
+    /**
+     * <p>
+     * LPARAM of the message. Default: 0
+     * </p>
+     */
+    private long LPARAM = 0;
+
+    /**
+     * <p>
+     * WPARAM of the message. Default: 0
+     * </p>
+     */
+    private long WPARAM = 0;
+
+    /**
+     * <p>
+     * A map of all parameters, associated with the message, created during the parsing of messages
+     * from the logs {@code param}-nodes.
+     * </p>
+     */
+    private Map<String, Object> params = new HashMap<String, Object>();
+
+    /**
+     * <p>
+     * the target GUI element to which the message was sent
+     * </p>
+     */
+    private MFCGUIElement target;
+
+    /**
+     * <p>
+     * an XML representation of the target to preserve it as it was when this message was created
+     * </p>
+     */
+    protected String targetXML;
+
+    /**
+     * <p>
+     * Constructor. Creates a new message with a given message type.
+     * </p>
+     * 
+     * @param type
+     *            type of the message
+     * @param currentMessageParameters 
+     * @param target 
+     */
+    public WindowsMessage(WindowsMessageType  type,
+                          MFCGUIElement       target,
+                          Map<String, Object> messageParameters)
+    {
+        this.type = type;
+        setTarget(target);
+        
+        for (Map.Entry<String, Object> entry : messageParameters.entrySet()) {
+            addParameter(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
+     * <p>
+     * Constructor. Creates a new message with a given message type.
+     * </p>
+     * 
+     * @param type
+     *            type of the message
+     */
+    public WindowsMessage(WindowsMessageType type)
+    {
+        this.type = type;
+    }
+
+    /**
+     * <p>
+     * Adds a parameter to the message.
+     * </p>
+     * 
+     * @param type
+     *            type descriptor of the parameter
+     * @param value
+     *            value of the parameter
+     */
+    public void addParameter(String type, Object value) {
+        params.put(type, value);
+        if (type.equals("LPARAM")) {
+            LPARAM = (Long) value;
+        }
+        else if (type.equals("WPARAM")) {
+            WPARAM = (Long) value;
+        }
+    }
+
+    /**
+     * <p>
+     * Returns the type of the message.
+     * </p>
+     * 
+     * @return type of the message
+     */
+    public WindowsMessageType getType() {
+        return type;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param target2
+     */
+    public void setTarget(MFCGUIElement target) {
+        this.target = target;
+        this.targetXML = target.toXML();
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @return
+     */
+    public MFCGUIElement getTarget() {
+        return target;
+    }
+    
+    /**
+     * <p>
+     * Returns the value of a parameter, given its type. If the parameter is not found, {@code null}
+     * is returned.
+     * </p>
+     * 
+     * @param type
+     *            type of the parameter
+     * @return value of the parameter
+     */
+    public Object getParameter(String type) {
+        return params.get(type);
+    }
+
+    /**
+     * <p>
+     * Two {@link WindowsMessage} are equal, if their {@link #type}, {@link #xmlWindowDescription},
+     * and {@link #params} are equal.
+     * </p>
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
      */
     @Override
-    public IReplayDecorator getDecorator() {
-        return MFCReplayDecorator.getInstance();
-    }
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        boolean isEqual = false;
+        if (other instanceof WindowsMessage) {
+            isEqual =
+                ((WindowsMessage) other).type == this.type &&
+                ((WindowsMessage) other).target.equals(this.target) &&
+                ((WindowsMessage) other).params.equals(this.params);
+        }
+        return isEqual;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        int multiplier = 17;
+        int hash = 42;
+
+        hash = multiplier * hash + type.hashCode();
+        hash = multiplier * hash + target.hashCode();
+        hash = multiplier * hash + params.hashCode();
+
+        return hash;
+    }
+
+    /**
+     * <p>
+     * Returns a string representation of the message of the form "msg[target=HWND;type=TYPE]".
+     * </p>
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "msg[target=" + getParameter("window.hwnd") + ";type=" + type + "]";
+    }
+
+    /**
+     * <p>
+     * Returns the LPARAM of a message.
+     * </p>
+     * 
+     * @return LPARAM of the message
+     */
+    public long getLPARAM() {
+        return LPARAM;
+    }
+
+    /**
+     * <p>
+     * Returns the WPARAM of a message.
+     * </p>
+     * 
+     * @return WPARAM of the message
+     */
+    public long getWPARAM() {
+        return WPARAM;
+    }
+
+    /**
+     * <p>
+     * Returns the number of parameters stored together with this message.
+     * </p>
+     * 
+     * @return number of parameters stored with this message
+     */
+    public int getNumParams() {
+        return params.size();
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @return
+     */
+    protected Map<String, Object> getParameters() {
+        return params;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @return
+     */
+    public String getTargetXML() {
+        return targetXML;
+    }
+
 }
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsMessageType.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsMessageType.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsMessageType.java	(revision 619)
@@ -0,0 +1,333 @@
+// Module    : $RCSfile: MessageType.java,v $
+// Version   : $Revision: 0.0 $  $Author: Patrick $  $Date: 26.11.2011 14:36:45 $
+// Project   : TaskTreePerformanceTest
+// Creation  : 2011 by Patrick
+// Copyright : Patrick Harms, 2011
+
+package de.ugoe.cs.quest.plugin.mfc.eventcore;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+public enum WindowsMessageType {
+    
+    WM_NULL(0),
+    WM_CREATE(1),
+    WM_DESTROY(2),
+    WM_MOVE(3),
+    WM_SIZE(5),
+    WM_ACTIVATE(6),
+    WM_SETFOCUS(7),
+    WM_KILLFOCUS(8),
+    WM_ENABLE(10),
+    WM_SETREDRAW(11),
+    WM_SETTEXT(12),
+    WM_GETTEXT(13),
+    WM_GETTEXTLENGTH(14),
+    WM_PAINT(15),
+    WM_CLOSE(16),
+    WM_QUERYENDSESSION(17),
+    WM_QUIT(18),
+    WM_QUERYOPEN(19),
+    WM_ERASEBKGND(20),
+    WM_SYSCOLORCHANGE(21),
+    WM_ENDSESSION(22),
+    WM_SHOWWINDOW(24),
+    WM_CTLCOLOR(25),
+    WM_WININICHANGE(26),
+    WM_DEVMODECHANGE(27),
+    WM_ACTIVATEAPP(28),
+    WM_FONTCHANGE(29),
+    WM_TIMECHANGE(30),
+    WM_CANCELMODE(31),
+    WM_SETCURSOR(32),
+    WM_MOUSEACTIVATE(33),
+    WM_CHILDACTIVATE(34),
+    WM_QUEUESYNC(35),
+    WM_GETMINMAXINFO(36),
+    WM_PAINTICON(38),
+    WM_ICONERASEBKGND(39),
+    WM_NEXTDLGCTL(40),
+    WM_SPOOLERSTATUS(42),
+    WM_DRAWITEM(43),
+    WM_MEASUREITEM(44),
+    WM_DELETEITEM(45),
+    WM_VKEYTOITEM(46),
+    WM_CHARTOITEM(47),
+    WM_SETFONT(48),
+    WM_GETFONT(49),
+    WM_SETHOTKEY(50),
+    WM_GETHOTKEY(51),
+    WM_QUERYDRAGICON(55),
+    WM_COMPAREITEM(57),
+    WM_GETOBJECT(61),
+    WM_COMPACTING(65),
+    WM_COMMNOTIFY(68),
+    WM_WINDOWPOSCHANGING(70),
+    WM_WINDOWPOSCHANGED(71),
+    WM_POWER(72),
+    WM_COPYDATA(74),
+    WM_CANCELJOURNAL(75),
+    WM_NOTIFY(78),
+    WM_INPUTLANGCHANGEREQUEST(80),
+    WM_INPUTLANGCHANGE(81),
+    WM_TCARD(82),
+    WM_HELP(83),
+    WM_USERCHANGED(84),
+    WM_NOTIFYFORMAT(85),
+    WM_CONTEXTMENU(123),
+    WM_STYLECHANGING(124),
+    WM_STYLECHANGED(125),
+    WM_DISPLAYCHANGE(126),
+    WM_GETICON(127),
+    WM_SETICON(128),
+    WM_NCCREATE(129),
+    WM_NCDESTROY(130),
+    WM_NCCALCSIZE(131),
+    WM_NCHITTEST(132),
+    WM_NCPAINT(133),
+    WM_NCACTIVATE(134),
+    WM_GETDLGCODE(135),
+    WM_SYNCPAINT(136),
+    WM_NCMOUSEMOVE(160),
+    WM_NCLBUTTONDOWN(161),
+    WM_NCLBUTTONUP(162),
+    WM_NCLBUTTONDBLCLK(163),
+    WM_NCRBUTTONDOWN(164),
+    WM_NCRBUTTONUP(165),
+    WM_NCRBUTTONDBLCLK(166),
+    WM_NCMBUTTONDOWN(167),
+    WM_NCMBUTTONUP(168),
+    WM_NCMBUTTONDBLCLK(169),
+    WM_NCXBUTTONDOWN(171),
+    WM_NCXBUTTONUP(172),
+    WM_NCXBUTTONDBLCLK(173),
+    SBM_SETPOS(224),
+    BM_CLICK(245),
+    WM_INPUT(255),
+    WM_KEYDOWN(256),
+    WM_KEYFIRST(256),
+    WM_KEYUP(257),
+    WM_CHAR(258),
+    WM_DEADCHAR(259),
+    WM_SYSKEYDOWN(260),
+    WM_SYSKEYUP(261),
+    WM_SYSCHAR(262),
+    WM_SYSDEADCHAR(263),
+    WM_KEYLAST(264),
+    WM_WNT_CONVERTREQUESTEX(265),
+    WM_CONVERTREQUEST(266),
+    WM_CONVERTRESULT(267),
+    WM_INTERIM(268),
+    WM_IME_STARTCOMPOSITION(269),
+    WM_IME_ENDCOMPOSITION(270),
+    WM_IME_COMPOSITION(271),
+    WM_IME_KEYLAST(271),
+    WM_INITDIALOG(272),
+    WM_COMMAND(273),
+    WM_SYSCOMMAND(274),
+    WM_TIMER(275),
+    WM_HSCROLL(276),
+    WM_VSCROLL(277),
+    WM_INITMENU(278),
+    WM_INITMENUPOPUP(279),
+    WM_MENUSELECT(287),
+    WM_MENUCHAR(288),
+    WM_ENTERIDLE(289),
+    WM_MENURBUTTONUP(290),
+    WM_MENUDRAG(291),
+    WM_MENUGETOBJECT(292),
+    WM_UNINTMENUPOPUP(293),
+    WM_MENUCOMMAND(294),
+    WM_CHANGEUISTATE(295),
+    WM_UPDATEUISTATE(296),
+    WM_QUERYUISTATE(297),
+    WM_CTLCOLORMSGBOX(306),
+    WM_CTLCOLOREDIT(307),
+    WM_CTLCOLORLISTBOX(308),
+    WM_CTLCOLORBTN(309),
+    WM_CTLCOLORDLG(310),
+    WM_CTLCOLORSCROLLBAR(311),
+    WM_CTLCOLORSTATIC(312),
+    CB_SHOWDROPDOWN(335),
+    LB_SETCURSEL(390),
+    WM_MOUSEFIRST(512),
+    WM_MOUSEMOVE(512),
+    WM_LBUTTONDOWN(513),
+    WM_LBUTTONUP(514),
+    WM_LBUTTONDBLCLK(515),
+    WM_RBUTTONDOWN(516),
+    WM_RBUTTONUP(517),
+    WM_RBUTTONDBLCLK(518),
+    WM_MBUTTONDOWN(519),
+    WM_MBUTTONUP(520),
+    WM_MBUTTONDBLCLK(521),
+    WM_MOUSELAST(521),
+    WM_MOUSEWHEEL(522),
+    WM_XBUTTONDOWN(523),
+    WM_XBUTTONUP(524),
+    WM_XBUTTONDBLCLK(525),
+    WM_USER(1024),
+    CB_SETCURSEL(334),
+    TBM_SETPOS(1029),
+    UDM_SETRANGE(1125),
+    TCM_SETCURSEL(4876);
+
+    /** the numerical representation of the message type */
+    private int mNumber;
+
+    /**
+     * @param number
+     */
+    WindowsMessageType(int number) {
+        mNumber = number;
+    }
+
+    /**
+     * @return Returns the number.
+     */
+    public int getNumber() {
+        return mNumber;
+    }
+
+    /**
+     * <p>
+     * Checks if the type of a message generated is a keyboard interaction.
+     * </p>
+     * 
+     * @param msgType
+     *            type of the message
+     * @return true if it is a keyboard interaction; false otherwise
+     */
+    public boolean isKeyMessage() {
+        boolean isKeyMsg = false;
+        switch (this)
+        {
+            case WM_KEYDOWN:
+            case WM_KEYUP:
+            case WM_SYSKEYDOWN:
+            case WM_SYSKEYUP:
+                isKeyMsg = true;
+                break;
+            default:
+                break;
+        }
+        return isKeyMsg;
+    }
+
+    /**
+     * <p>
+     * Checks if the type of a message indicates that the mouse has been pressed down.
+     * </p>
+     * 
+     * @param msgType
+     *            type of the message
+     * @return true if it is mouse-down message; false otherwise
+     */
+    public boolean isDownMessage() {
+        boolean isDownMsg = false;
+        switch (this)
+        {
+            case WM_LBUTTONDOWN:
+            case WM_RBUTTONDOWN:
+            case WM_MBUTTONDOWN:
+            case WM_XBUTTONDOWN:
+            case WM_NCLBUTTONDOWN:
+            case WM_NCRBUTTONDOWN:
+            case WM_NCMBUTTONDOWN:
+            case WM_NCXBUTTONDOWN:
+                isDownMsg = true;
+                break;
+            default:
+                break;
+        }
+        return isDownMsg;
+    }
+
+    /**
+     * <p>
+     * Checks if the type of a message indicates that a double click has been performed.
+     * </p>
+     * 
+     * @param msgType
+     *            type of the message
+     * @return true if it is a double click message; false otherwise
+     */
+    public boolean isDblclkMessage() {
+        boolean isDblclkMsg = false;
+        switch (this)
+        {
+            case WM_LBUTTONDBLCLK:
+            case WM_RBUTTONDBLCLK:
+            case WM_MBUTTONDBLCLK:
+            case WM_XBUTTONDBLCLK:
+            case WM_NCLBUTTONDBLCLK:
+            case WM_NCRBUTTONDBLCLK:
+            case WM_NCMBUTTONDBLCLK:
+            case WM_NCXBUTTONDBLCLK:
+                isDblclkMsg = true;
+                break;
+            default:
+                break;
+        }
+        return isDblclkMsg;
+    }
+
+    /**
+     * <p>
+     * Checks if the type of a message indicates that the mouse has been released.
+     * </p>
+     * 
+     * @param msgType
+     *            type of the message
+     * @return true if it is mouse-up message; false otherwise
+     */
+    public boolean isUpMessage() {
+        boolean isUpMsg = false;
+        switch (this)
+        {
+            case WM_LBUTTONUP:
+            case WM_RBUTTONUP:
+            case WM_MBUTTONUP:
+            case WM_XBUTTONUP:
+            case WM_NCLBUTTONUP:
+            case WM_NCRBUTTONUP:
+            case WM_NCMBUTTONUP:
+            case WM_NCXBUTTONUP:
+                isUpMsg = true;
+                break;
+            default:
+                break;
+        }
+        return isUpMsg;
+    }
+
+    /**
+     *
+     */
+    public static WindowsMessageType parseMessageType(String numberString) {
+        try {
+            int number = Integer.parseInt(numberString);
+            return valueOf(number);
+        }
+        catch (NumberFormatException e) {
+            return WindowsMessageType.valueOf(WindowsMessageType.class, numberString);
+        }
+    }
+
+    /**
+     *
+     */
+    public static WindowsMessageType valueOf(int number) {
+        for (WindowsMessageType type : WindowsMessageType.values()) {
+            if (type.mNumber == number) {
+                return type;
+            }
+        }
+
+        throw new IllegalArgumentException("there is no message type with number " + number);
+    }
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsVirtualKey.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsVirtualKey.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowsVirtualKey.java	(revision 619)
@@ -0,0 +1,253 @@
+//-------------------------------------------------------------------------------------------------
+// Module    : $RCSfile: VirtualKey.java,v $
+// Version   : $Revision: 0.0 $  $Author: Patrick $  $Date: 27.11.2011 18:35:34 $
+// Project   : TaskTreePerformanceTest
+// Creation  : 2011 by Patrick
+// Copyright : Patrick Harms, 2011
+//-------------------------------------------------------------------------------------------------
+
+package de.ugoe.cs.quest.plugin.mfc.eventcore;
+
+import de.ugoe.cs.tasktree.keyboardmaps.VirtualKey;
+
+//-------------------------------------------------------------------------------------------------
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+// -------------------------------------------------------------------------------------------------
+
+public enum WindowsVirtualKey
+{
+    // VK_LBUTTON (0x01, "Left mouse button"),
+    // VK_RBUTTON (0x02, "Right mouse button"),
+    VK_CANCEL(0x03, VirtualKey.CANCEL),
+    // VK_MBUTTON (0x04, "Middle mouse button (three-button mouse)"),
+    // VK_XBUTTON1 (0x05, "X1 mouse button"),
+    // VK_XBUTTON2 (0x06, "X2 mouse button"),
+    // - (0x07, "Undefined"),
+    VK_BACK(0x08, VirtualKey.BACK_SPACE),
+    VK_TAB(0x09, VirtualKey.TAB),
+    // - (0x0A-0B, "Reserved"),
+    VK_CLEAR(0x0C, VirtualKey.CLEAR),
+    VK_RETURN(0x0D, VirtualKey.ENTER),
+    // - (0x0E-0F, "Undefined"),
+    VK_SHIFT(0x10, VirtualKey.SHIFT),
+    VK_CONTROL(0x11, VirtualKey.CONTROL),
+    VK_MENU(0x12, VirtualKey.ALT),
+    VK_PAUSE(0x13, VirtualKey.PAUSE),
+    VK_CAPITAL(0x14, VirtualKey.CAPS_LOCK),
+    VK_KANA(0x15, VirtualKey.KANA),
+    // VK_HANGUEL (0x15, VirtualKey.HANGUEL),
+    // VK_HANGUL (0x15, "IME Hangul mode"),
+    // - (0x16, "Undefined"),
+    // VK_JUNJA (0x17, VirtualKey.J),
+    VK_FINAL(0x18, VirtualKey.FINAL),
+    // VK_HANJA (0x19, "IME Hanja mode"),
+    VK_KANJI(0x19, VirtualKey.KANJI),
+    // - (0x1A, "Undefined"),
+    VK_ESCAPE(0x1B, VirtualKey.ESCAPE), VK_CONVERT(0x1C, VirtualKey.CONVERT),
+    VK_NONCONVERT(0x1D, VirtualKey.NONCONVERT),
+    VK_ACCEPT(0x1E, VirtualKey.ACCEPT),
+    VK_MODECHANGE(0x1F, VirtualKey.MODECHANGE),
+
+    VK_SPACE(0x20, VirtualKey.SPACE),
+    VK_PRIOR(0x21, VirtualKey.PAGE_UP),
+    VK_NEXT(0x22, VirtualKey.PAGE_DOWN),
+    VK_END(0x23, VirtualKey.END),
+    VK_HOME(0x24, VirtualKey.HOME),
+    VK_LEFT(0x25, VirtualKey.LEFT),
+    VK_UP(0x26, VirtualKey.UP),
+    VK_RIGHT(0x27, VirtualKey.RIGHT),
+    VK_DOWN(0x28, VirtualKey.DOWN),
+    // VK_SELECT (0x29, VirtualKey.),
+    VK_PRINT(0x2A, VirtualKey.PRINTSCREEN),
+    // VK_EXECUTE (0x2B, VirtualKey.EXECUTE),
+    VK_SNAPSHOT(0x2C, VirtualKey.PRINTSCREEN), VK_INSERT(0x2D, VirtualKey.INSERT), VK_DELETE(0x2E,
+        VirtualKey.DELETE), VK_HELP(0x2F, VirtualKey.HELP), DIGIT_0(0x30, VirtualKey.DIGIT_0),
+    DIGIT_1(0x31, VirtualKey.DIGIT_1), DIGIT_2(0x32, VirtualKey.DIGIT_2), DIGIT_3(0x33,
+        VirtualKey.DIGIT_3), DIGIT_4(0x34, VirtualKey.DIGIT_4), DIGIT_5(0x35, VirtualKey.DIGIT_5),
+    DIGIT_6(0x36, VirtualKey.DIGIT_6),
+    DIGIT_7(0x37, VirtualKey.DIGIT_7),
+    DIGIT_8(0x38, VirtualKey.DIGIT_8),
+    DIGIT_9(0x39, VirtualKey.DIGIT_9),
+    // - (0x3A-40, "Undefined"),
+    A(0x41, VirtualKey.LETTER_A), B(0x42, VirtualKey.LETTER_B), C(0x43, VirtualKey.LETTER_C), D(
+        0x44, VirtualKey.LETTER_D), E(0x45, VirtualKey.LETTER_E), F(0x46, VirtualKey.LETTER_F), G(
+        0x47, VirtualKey.LETTER_G), H(0x48, VirtualKey.LETTER_H), I(0x49, VirtualKey.LETTER_I), J(
+        0x4A, VirtualKey.LETTER_J), K(0x4B, VirtualKey.LETTER_K), L(0x4C, VirtualKey.LETTER_L), M(
+        0x4D, VirtualKey.LETTER_M), N(0x4E, VirtualKey.LETTER_N), O(0x4F, VirtualKey.LETTER_O), P(
+        0x50, VirtualKey.LETTER_P), Q(0x51, VirtualKey.LETTER_Q), R(0x52, VirtualKey.LETTER_R), S(
+        0x53, VirtualKey.LETTER_S),
+    T(0x54, VirtualKey.LETTER_T),
+    U(0x55, VirtualKey.LETTER_U),
+    V(0x56, VirtualKey.LETTER_V),
+    W(0x57, VirtualKey.LETTER_W),
+    X(0x58, VirtualKey.LETTER_X),
+    Y(0x59, VirtualKey.LETTER_Y),
+    Z(0x5A, VirtualKey.LETTER_Z),
+    VK_LWIN(0x5B, VirtualKey.WINDOWS),
+    VK_RWIN(0x5C, VirtualKey.WINDOWS),
+    // VK_APPS (0x5D, "Applications key (Natural keyboard)"),
+    // - (0x5E, "Reserved"),
+    // VK_SLEEP (0x5F, VirtualKey.SLEEP),
+    VK_NUMPAD0(0x60, VirtualKey.NUMPAD_0), VK_NUMPAD1(0x61, VirtualKey.NUMPAD_1), VK_NUMPAD2(0x62,
+        VirtualKey.NUMPAD_2), VK_NUMPAD3(0x63, VirtualKey.NUMPAD_3), VK_NUMPAD4(0x64,
+        VirtualKey.NUMPAD_4), VK_NUMPAD5(0x65, VirtualKey.NUMPAD_5), VK_NUMPAD6(0x66,
+        VirtualKey.NUMPAD_6), VK_NUMPAD7(0x67, VirtualKey.NUMPAD_7), VK_NUMPAD8(0x68,
+        VirtualKey.NUMPAD_8), VK_NUMPAD9(0x69, VirtualKey.NUMPAD_9), VK_MULTIPLY(0x6A,
+        VirtualKey.MULTIPLY), VK_ADD(0x6B, VirtualKey.ADD),
+    VK_SEPARATOR(0x6C, VirtualKey.SEPARATOR), VK_SUBTRACT(0x6D, VirtualKey.SUBTRACT), VK_DECIMAL(
+        0x6E, VirtualKey.DECIMAL), VK_DIVIDE(0x6F, VirtualKey.DIVIDE), VK_F1(0x70, VirtualKey.F1),
+    VK_F2(0x71, VirtualKey.F2), VK_F3(0x72, VirtualKey.F3), VK_F4(0x73, VirtualKey.F4), VK_F5(0x74,
+        VirtualKey.F5), VK_F6(0x75, VirtualKey.F6), VK_F7(0x76, VirtualKey.F7), VK_F8(0x77,
+        VirtualKey.F8), VK_F9(0x78, VirtualKey.F9), VK_F10(0x79, VirtualKey.F10), VK_F11(0x7A,
+        VirtualKey.F11), VK_F12(0x7B, VirtualKey.F12), VK_F13(0x7C, VirtualKey.F13), VK_F14(0x7D,
+        VirtualKey.F14), VK_F15(0x7E, VirtualKey.F15), VK_F16(0x7F, VirtualKey.F16), VK_F17(0x80,
+        VirtualKey.F17), VK_F18(0x81, VirtualKey.F18), VK_F19(0x82, VirtualKey.F19), VK_F20(0x83,
+        VirtualKey.F20), VK_F21(0x84, VirtualKey.F21), VK_F22(0x85, VirtualKey.F22), VK_F23(0x86,
+        VirtualKey.F23), VK_F24(0x87, VirtualKey.F24),
+    // - (0x88-8F, "Unassigned"),
+    VK_NUMLOCK(0x90, VirtualKey.NUM_LOCK),
+    VK_SCROLL(0x91, VirtualKey.SCROLL_LOCK),
+    // - (0x92-96, "OEM specific"),
+    // - (0x97-9F, "Unassigned"),
+    VK_LSHIFT(0xA0, VirtualKey.SHIFT), VK_RSHIFT(0xA1, VirtualKey.SHIFT), VK_LCONTROL(0xA2,
+        VirtualKey.CONTROL), VK_RCONTROL(0xA3, VirtualKey.CONTROL), VK_LMENU(0xA4, VirtualKey.ALT),
+    VK_RMENU(0xA5, VirtualKey.ALT_GRAPH),
+    // VK_BROWSER_BACK (0xA6, VirtualKey.BROWSER_BACK),
+    // VK_BROWSER_FORWARD (0xA7, VirtualKey.BROWSER_FORWARD),
+    VK_BROWSER_REFRESH(0xA8, VirtualKey.F5), VK_BROWSER_STOP(0xA9, VirtualKey.STOP),
+    // VK_BROWSER_SEARCH (0xAA, VirtualKey.BROWSER_SEARCH),
+    // VK_BROWSER_FAVORITES (0xAB, VirtualKey.BROWSER_FAVORITES),
+    // VK_BROWSER_HOME (0xAC, VirtualKey.BROWSER_HOME),
+    // VK_VOLUME_MUTE (0xAD, VirtualKey.VOLUME_MUTE),
+    // VK_VOLUME_DOWN (0xAE, VirtualKey.VOLUME_DOWN),
+    // VK_VOLUME_UP (0xAF, VirtualKey.VOLUME_UP),
+    // VK_MEDIA_NEXT_TRACK (0xB0, VirtualKey.MEDIA_NEXT_TRACK),
+    // VK_MEDIA_PREV_TRACK (0xB1, VirtualKey.MEDIA_PREV_TRACK),
+    // VK_MEDIA_STOP (0xB2, VirtualKey.MEDIA_STOP),
+    // VK_MEDIA_PLAY_PAUSE (0xB3, VirtualKey.MEDIA_PLAY_PAUSE),
+    // VK_LAUNCH_MAIL (0xB4, VirtualKey.LAUNCH_MAIL),
+    // VK_LAUNCH_MEDIA_SELECT (0xB5, VirtualKey.LAUNCH_MEDIA_SELECT),
+    // VK_LAUNCH_APP1 (0xB6, VirtualKey.LAUNCH_APP1),
+    // VK_LAUNCH_APP2 (0xB7, VirtualKey.LAUNCH_APP2),
+    // - (0xB8-B9, "Reserved"),
+    // VK_OEM_1 (0xBA, "Used for miscellaneous characters; it can vary by keyboard." +
+    // "For the US standard keyboard, the ';:' key"),
+    VK_OEM_PLUS(0xBB, VirtualKey.PLUS), VK_OEM_COMMA(0xBC, VirtualKey.COMMA), VK_OEM_MINUS(0xBD,
+        VirtualKey.MINUS), VK_OEM_PERIOD(0xBE, VirtualKey.PERIOD);
+    // VK_OEM_2 (0xBF, "Used for miscellaneous characters; it can vary by keyboard." +
+    // "For the US standard keyboard, the '/?' key"),
+    // VK_OEM_3 (0xC0, "Used for miscellaneous characters; it can vary by keyboard." +
+    // "For the US standard keyboard, the '`~' key"),
+    // - (0xC1-D7, "ReserveD, "- (0xD8-DA, "Unassigned"),
+    // VK_OEM_4 (0xDB, "Used for miscellaneous characters; it can vary by keyboard." +
+    // "For the US standard keyboard, the '[{' key"),
+    // VK_OEM_5 (0xDC, "Used for miscellaneous characters; it can vary by keyboard." +
+    // "For the US standard keyboard, the '\\|' key"),
+    // VK_OEM_6 (0xDD, "Used for miscellaneous characters; it can vary by keyboard." +
+    // "For the US standard keyboard, the ']}' key"),
+    // VK_OEM_7 (0xDE, "Used for miscellaneous characters; it can vary by keyboard." +
+    // "For the US standard keyboard, the 'single-quote/double-quote' key"),
+    // VK_OEM_8 (0xDF, "Used for miscellaneous characters; it can vary by keyboard."),
+    // - (0xE0, "Reserved"),
+    // - (0xE1, "OEM specific"),
+    // VK_OEM_102 (0xE2, "Either the angle bracket key or the backslash key on the RT 102-key" +
+    // "keyboard"),
+    // - (0xE3-E4, "OEM specific"),
+    // VK_PROCESSKEY (0xE5, VirtualKey.EXECUTE),
+    // - (0xE6, "OEM specific"),
+    // VK_PACKET (0xE7, "Used to pass Unicode characters as if they were keystrokes. The " +
+    // "VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard " +
+    // "input methods. For more information, see Remark in KEYBDINPUT, SendInput, " +
+    // "WM_KEYDOWN, and WM_KEYUP"),
+    // - (0xE8, "Unassigned (0xE9-F5, "OEM specific"),
+    // VK_ATTN (0xF6, "Attn key"),
+    // VK_CRSEL (0xF7, "CrSel key"),
+    // VK_EXSEL (0xF8, "ExSel key"),
+    // VK_EREOF (0xF9, "Erase EOF key"),
+    // VK_PLAY (0xFA, VirtualKey.MEDIA_PLAY_PAUSE);
+    // VK_ZOOM (0xFB, "Zoom key"),
+    // VK_NONAME (0xFC, "Reserved"),
+    // VK_PA1 (0xFD, "PA1 key"),
+    // VK_OEM_CLEAR (0xFE, "Clear key");
+
+    /** the id of the virtual key */
+    private int mNumber;
+
+    /** the <code>Key</code> represented by this virtual key */
+    private VirtualKey mRepresentedKey;
+
+    // -----------------------------------------------------------------------------------------------
+    /**
+     * @param number
+     */
+    // -----------------------------------------------------------------------------------------------
+    WindowsVirtualKey(int number, VirtualKey representedKey)
+    {
+        mNumber = number;
+        mRepresentedKey = representedKey;
+    }
+
+    // -----------------------------------------------------------------------------------------------
+    /**
+     * @return Returns the number.
+     */
+    // -----------------------------------------------------------------------------------------------
+    int getNumber()
+    {
+        return mNumber;
+    }
+
+    // -----------------------------------------------------------------------------------------------
+    /**
+   *
+   */
+    // -----------------------------------------------------------------------------------------------
+    public static WindowsVirtualKey parseVirtualKey(String string)
+    {
+        for (WindowsVirtualKey virtualKey : WindowsVirtualKey.values())
+        {
+            if (virtualKey.mNumber == Integer.parseInt(string))
+            {
+                return virtualKey;
+            }
+        }
+
+        throw new IllegalArgumentException("there is no virtual key with id " + string);
+    }
+
+    // -----------------------------------------------------------------------------------------------
+    /**
+   *
+   */
+    // -----------------------------------------------------------------------------------------------
+    public static WindowsVirtualKey valueOf(int number)
+    {
+        for (WindowsVirtualKey virtualKey : WindowsVirtualKey.values())
+        {
+            if (virtualKey.mNumber == number)
+            {
+                return virtualKey;
+            }
+        }
+
+        throw new IllegalArgumentException("there is no virtual key with number " + number);
+    }
+
+    // -----------------------------------------------------------------------------------------------
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    // -----------------------------------------------------------------------------------------------
+    public VirtualKey getKey()
+    {
+        return mRepresentedKey;
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCButton.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCButton.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCButton.java	(revision 619)
@@ -0,0 +1,34 @@
+// Module    : $RCSfile: MFCButton.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 21.08.2012 $
+// Project   : quest-plugin-mfc-blub
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.IButton;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 21.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCButton extends MFCGUIElement implements IButton {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     */
+    public MFCButton(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCCanvas.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCCanvas.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCCanvas.java	(revision 619)
@@ -0,0 +1,35 @@
+// Module    : $RCSfile: MFCCanvas.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 23.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.ICanvas;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 23.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCCanvas extends MFCGUIElement implements ICanvas {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     * @param parent
+     */
+    public MFCCanvas(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCComboBox.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCComboBox.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCComboBox.java	(revision 619)
@@ -0,0 +1,35 @@
+// Module    : $RCSfile: MFCComboBox.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 23.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.IComboBox;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 23.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCComboBox extends MFCGUIElement implements IComboBox {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     * @param parent
+     */
+    public MFCComboBox(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCDialog.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCDialog.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCDialog.java	(revision 619)
@@ -0,0 +1,34 @@
+// Module    : $RCSfile: MFCDialog.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 21.08.2012 $
+// Project   : quest-plugin-mfc-blub
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.IDialog;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 21.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCDialog extends MFCWindow implements IDialog {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     */
+    public MFCDialog(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCGUIElement.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCGUIElement.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCGUIElement.java	(revision 619)
@@ -0,0 +1,110 @@
+// Module    : $RCSfile: GUIElementFromReplay.java,v $
+// Version   : $Revision: 0.0 $  $Author: Patrick $  $Date: 27.11.2011 17:18:00 $
+// Project   : TaskTreePerformanceTest
+// Creation  : 2011 by Patrick
+// Copyright : Patrick Harms, 2011
+
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.AbstractDefaultGUIElement;
+import de.ugoe.cs.quest.eventcore.guimodel.IGUIElementSpec;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+public abstract class MFCGUIElement extends AbstractDefaultGUIElement {
+    
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * @param name
+     * @param id
+     * @param isModal
+     */
+    public MFCGUIElement(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.quest.eventcore.IEventTarget#getPlatform()
+     */
+    @Override
+    public String getPlatform() {
+        return "MFC";
+    }
+
+    /**
+     * @return Returns the id.
+     */
+    public String getId() {
+        return Long.toString(((MFCGUIElementSpec) super.getSpecification()).getHwnd());
+    }
+
+    /**
+     * @return Returns the name.
+     */
+    public String getType() {
+        return ((MFCGUIElementSpec) super.getSpecification()).getType();
+    }
+
+    /**
+     * @return Returns the name.
+     */
+    public String getName() {
+        return ((MFCGUIElementSpec) super.getSpecification()).getName();
+    }
+
+    /**
+     * @return Returns the isModal.
+     */
+    public boolean isModal() {
+        return ((MFCGUIElementSpec) super.getSpecification()).isModal();
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @return
+     */
+    public int getResourceId() {
+        return ((MFCGUIElementSpec) super.getSpecification()).getResourceId();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.quest.eventcore.guimodel.IGUIElement#updateSpecification(de.ugoe.cs.quest.eventcore.guimodel.IGUIElementSpec)
+     */
+    @Override
+    public void updateSpecification(IGUIElementSpec furtherSpec) {
+        ((MFCGUIElementSpec) super.getSpecification()).update(furtherSpec);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return super.getSpecification().toString();
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     */
+    public String toXML() {
+        if (getParent() != null) {
+            return
+                ((MFCGUIElement) getParent()).toXML() +
+                ((MFCGUIElementSpec) super.getSpecification()).toXML();
+        }
+        else {
+            return ((MFCGUIElementSpec) super.getSpecification()).toXML();
+        }
+    }
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCGUIElementSpec.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCGUIElementSpec.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCGUIElementSpec.java	(revision 619)
@@ -0,0 +1,392 @@
+
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.quest.eventcore.guimodel.IGUIElementSpec;
+import de.ugoe.cs.util.StringTools;
+
+/**
+ * <p>
+ * This class implements a node in the {@link WindowTree} that is maintained during parsing a
+ * session.
+ * </p>
+ * <p>
+ * The window tree is structure that contains the hierarchy of the windows of a application as well
+ * as basic information about each window: the hwnd; its name; its resource id; its class name.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ */
+public class MFCGUIElementSpec implements IGUIElementSpec {
+
+    /**
+     * <p>
+     * current name of the window
+     * </p>
+     */
+    private String name;
+
+    /**
+     * <p>
+     * previous names of the window as it may have changed over time.
+     * </p>
+     */
+    private List<String> formerNames = new ArrayList<String>();
+
+    /**
+     * <p>
+     * Handle of the window. Used as unique identifier during its existence.
+     * </p>
+     */
+    private long hwnd;
+
+    /**
+     * <p>
+     * previous handles of the window as the window may have been destroyed and recreated
+     * </p>
+     */
+    private List<Long> formerHwnds = new ArrayList<Long>();
+
+    /**
+     * <p>
+     * Resource id of the window.
+     * </p>
+     */
+    private final int resourceId;
+
+    /**
+     * <p>
+     * type (class name) of the window.
+     * </p>
+     */
+    private final String type;
+
+    /**
+     * <p>
+     * True, if the window is modal.
+     * </p>
+     */
+    private final boolean isModal;
+
+    /**
+     * <p>
+     * Creates a new WindowTreeNode.
+     * </p>
+     * <p>
+     * The constructor is protected WindowTreeNode may only be created from the WindowTree.
+     * </p>
+     * 
+     * @param hwnd
+     *            hwnd of the window
+     * @param parent
+     *            reference to the parent's WindowTreeNode
+     * @param name
+     *            name of the window
+     * @param resourceId
+     *            resource id of the window
+     * @param type
+     *            type, i.e. class name of the window
+     * @param isModal
+     *            modality of the window
+     */
+    protected MFCGUIElementSpec(long    hwnd,
+                                String  name,
+                                int     resourceId,
+                                String  type,
+                                boolean isModal)
+    {
+        this.hwnd = hwnd;
+        this.name = name;
+        this.resourceId = resourceId;
+        this.type = type;
+        this.isModal = isModal;
+    }
+
+    /**
+     * <p>
+     * Returns the name of the window.
+     * </p>
+     * 
+     * @return name of the window
+     */
+    public String getName() {
+        StringBuffer names = new StringBuffer();
+        
+        if (name != null) {
+            names.append('"');
+            names.append(name);
+            names.append('"');
+        }
+        else {
+            names.append("NOT_SET");
+        }
+        
+        if (formerNames.size() > 0) {
+            
+            names.append(" (aka ");
+            
+            for (int i = 0; i < formerNames.size(); i++) {
+                if (i > 0) {
+                    names.append("/");
+                }
+
+                names.append('"');
+                names.append(formerNames.get(i));
+                names.append('"');
+            }
+            
+            names.append(")");
+        }
+        
+        return names.toString();
+    }
+
+    /**
+     * <p>
+     * Returns the hwnd of the window.
+     * </p>
+     * 
+     * @return hwnd of the window
+     */
+    public long getHwnd() {
+        return hwnd;
+    }
+
+    /**
+     * <p>
+     * Returns the resource id of the window.
+     * </p>
+     * 
+     * @return resource id of the window
+     */
+    public int getResourceId() {
+        return resourceId;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.quest.eventcore.guimodel.IGUIElementSpec#getType()
+     */
+    @Override
+    public String getType() {
+        return type;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @return
+     */
+    public boolean isModal() {
+        return isModal;
+    }
+
+    /**
+     * <p>
+     * Sets the name of the window.
+     * </p>
+     * 
+     * @param text
+     *            new name of the window
+     */
+    public void setName(String newName) {
+        if ((this.name != null) &&
+            (!this.name.equals(newName)) &&
+            (!this.formerNames.contains(this.name)))
+        {
+            this.formerNames.add(this.name);
+        }
+        
+        this.name = newName;
+    }
+
+    /**
+     * <p>
+     * Sets the hwnd of the window.
+     * </p>
+     * 
+     * @param text
+     *            new name of the window
+     */
+    public void setHwnd(long newHwnd) {
+        if (!this.formerHwnds.contains(this.hwnd)) {
+            this.formerHwnds.add(this.hwnd);
+        }
+        
+        this.hwnd = newHwnd;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.quest.eventcore.guimodel.IGUIElementSpec#getSimilarity(de.ugoe.cs.quest.eventcore.guimodel.IGUIElementSpec)
+     */
+    @Override
+    public boolean getSimilarity(IGUIElementSpec other) {
+        
+        if (this == other) {
+            return true;
+        }
+        
+        if (!(other instanceof MFCGUIElementSpec)) {
+            return false;
+        }
+        
+        MFCGUIElementSpec otherSpec = (MFCGUIElementSpec) other;
+
+        if ((type != otherSpec.type) && ((type != null) && (!type.equals(otherSpec.type)))) {
+            return false;
+        }
+
+        if (isModal != otherSpec.isModal) {
+            return false;
+        }
+
+        if (resourceId != otherSpec.resourceId) {
+            return false;
+        }
+
+        // up to now, we compared, if the basics match. Now lets compare the id and the
+        // name. Both may change. The name may be reset (e.g. the title of a frame using the
+        // asterisk in the case data was changed). The id may change if e.g. a dialog is closed
+        // and reopend, i.e. a new instance is created. If one of them stays the same, then
+        // similarity is given. Therefore these are the first two comparisons
+        
+        if (hwnd == otherSpec.hwnd) {
+            return true;
+        }
+        
+        if ((name != null) && (name.equals(otherSpec.name))) {
+            return true;
+        }
+        
+        if ((((name == null) && (otherSpec.name == null)) ||
+             (("".equals(name)) && ("".equals(otherSpec.name)))) &&
+            (formerNames.size() == 0) && (otherSpec.formerNames.size() == 0))
+        {
+            return true;
+        }
+        
+        // if the hwnd and the name did not stay the same, then the name should be checked first.
+        // the current name of one of the specs must be contained in the former names of the
+        // respective other spec for similarity. Either of the specs should contain the name of the
+        // respective other spec in its former names. We can rely on this, as in the MFC context
+        // we get to know each name change. I.e. although currently the names of the specs differ,
+        // once they were identical. But it is sufficient to do it for the current names of the
+        // elements, as only one of them may have experienced more name changes then the other.
+
+        if ((otherSpec.name != null) && formerNames.contains(otherSpec.name))
+        {
+            return true;
+        }
+
+        if ((name != null) && otherSpec.formerNames.contains(name)) {
+            return true;
+        }
+        
+        // ok. Even the names to not match. This is usually a clear indication, that the elements
+        // are distinct. However, we check, if the former handles matched. This is very unlikely
+        // to happen. But it may occur, if a GUI element does not have a name or its name stays
+        // the empty string and if this GUI element is created, destroyed, and created again.
+
+        if (formerHwnds.contains(otherSpec.hwnd) || otherSpec.formerHwnds.contains(hwnd)) {
+            return true;
+        }
+
+        // now we can be really sure, that the GUI elements differ
+        
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.quest.eventcore.guimodel.IGUIElementSpec#equals(IGUIElementSpec)
+     */
+    @Override
+    public boolean equals(IGUIElementSpec other) {
+        
+        if (this == other) {
+            return true;
+        }
+        
+        if (!(other instanceof MFCGUIElementSpec)) {
+            return false;
+        }
+        
+        MFCGUIElementSpec otherSpec = (MFCGUIElementSpec) other;
+        
+        return
+            (hwnd == otherSpec.hwnd) && (isModal == otherSpec.isModal) &&
+            (resourceId == otherSpec.resourceId) &&
+            ((type == otherSpec.type) || ((type != null) && (type.equals(otherSpec.type)))) &&
+            ((name == otherSpec.name) || ((name != null) && (name.equals(otherSpec.name))));
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        // reuse only invariable elements
+        return (type + isModal + resourceId).hashCode();
+    }
+
+    /**
+     * <p>
+     * Returns a string identfier of the window:<br>
+     * {@code [resourceId;"windowName";"className";modality]}
+     * </p>
+     * 
+     * @return identifier string of the window
+     */
+    @Override
+    public String toString() {
+        return "[" + resourceId + ";" + getName() + ";\"" + type + "\";" + isModal + ";" +
+            hwnd + "]";
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     */
+    String toXML() {
+        return
+            "<window name=\"" + (name != null ? StringTools.xmlEntityReplacement(name) : "") +
+            "\" class=\"" + StringTools.xmlEntityReplacement(type) +
+            "\" resourceId=\"" + resourceId + "\" isModal=\"" +
+            isModal + "\" hwnd=\"" + hwnd + "\"" + "/>";
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param furtherSpec
+     */
+    void update(IGUIElementSpec furtherSpec) {
+        MFCGUIElementSpec other = (MFCGUIElementSpec) furtherSpec;
+        
+        if (other != this) {
+            for (long formerHwnd : other.formerHwnds) {
+                setHwnd(formerHwnd);
+            }
+
+            if (hwnd != other.hwnd) {
+                hwnd = other.hwnd;
+            }
+
+            for (String formerName : other.formerNames) {
+                setName(formerName);
+            }
+
+            if ((name != other.name) && (name != null) && (!name.equals(other.name)))
+            {
+                setName(other.name);
+            }
+        }
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCListBox.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCListBox.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCListBox.java	(revision 619)
@@ -0,0 +1,35 @@
+// Module    : $RCSfile: MFCListBox.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 23.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.IListBox;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 23.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCListBox extends MFCGUIElement implements IListBox {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     * @param parent
+     */
+    public MFCListBox(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCPanel.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCPanel.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCPanel.java	(revision 619)
@@ -0,0 +1,35 @@
+// Module    : $RCSfile: MFCPanel.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 23.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.IPanel;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 23.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCPanel extends MFCGUIElement implements IPanel {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     * @param parent
+     */
+    public MFCPanel(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCTabbedPane.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCTabbedPane.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCTabbedPane.java	(revision 619)
@@ -0,0 +1,35 @@
+// Module    : $RCSfile: MFCTabbedPane.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 23.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.ITabbedPane;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 23.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCTabbedPane extends MFCGUIElement implements ITabbedPane {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     * @param parent
+     */
+    public MFCTabbedPane(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCTextArea.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCTextArea.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCTextArea.java	(revision 619)
@@ -0,0 +1,34 @@
+// Module    : $RCSfile: MFCTextArea.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 21.08.2012 $
+// Project   : quest-plugin-mfc-blub
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.ITextArea;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 21.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCTextArea extends MFCGUIElement implements ITextArea {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     */
+    public MFCTextArea(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCToolBar.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCToolBar.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCToolBar.java	(revision 619)
@@ -0,0 +1,35 @@
+// Module    : $RCSfile: MFCToolBar.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 23.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.IToolBar;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 23.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCToolBar extends MFCGUIElement implements IToolBar {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     * @param parent
+     */
+    public MFCToolBar(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCTrackBar.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCTrackBar.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCTrackBar.java	(revision 619)
@@ -0,0 +1,35 @@
+// Module    : $RCSfile: MFCTrackBar.java,v $
+// Version   : $Revision: 0.0 $  $Author: pharms $  $Date: 23.08.2012 $
+// Project   : quest-plugin-mfc
+// Creation  : 2012 by pharms
+// Copyright : Patrick Harms, 2012
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.ITrackBar;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 23.08.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class MFCTrackBar extends MFCGUIElement implements ITrackBar {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param specification
+     * @param parent
+     */
+    public MFCTrackBar(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCWindow.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCWindow.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/MFCWindow.java	(revision 619)
@@ -0,0 +1,31 @@
+// Module    : $RCSfile: WindowFromReplay.java,v $
+// Version   : $Revision: 0.0 $  $Author: Patrick $  $Date: 27.11.2011 18:26:10 $
+// Project   : TaskTreePerformanceTest
+// Creation  : 2011 by Patrick
+// Copyright : Patrick Harms, 2011
+
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import de.ugoe.cs.quest.eventcore.guimodel.IFrame;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+public class MFCWindow extends MFCGUIElement implements IFrame {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * @param name
+     * @param id
+     * @param isModal
+     */
+    public MFCWindow(MFCGUIElementSpec specification, MFCGUIElement parent) {
+        super(specification, parent);
+    }
+
+}
Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/WindowTree.java
===================================================================
--- trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/WindowTree.java	(revision 619)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/WindowTree.java	(revision 619)
@@ -0,0 +1,290 @@
+
+package de.ugoe.cs.quest.plugin.mfc.guimodel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import de.ugoe.cs.quest.eventcore.guimodel.GUIElementFactory;
+import de.ugoe.cs.quest.eventcore.guimodel.GUIModel;
+import de.ugoe.cs.quest.eventcore.guimodel.GUIModelException;
+import de.ugoe.cs.quest.eventcore.guimodel.IGUIElementFactory;
+
+
+/**
+ * <p>
+ * This class provides an the interfaces for window trees.
+ * </p>
+ * <p>
+ * The window tree represents the hierarchical structure of the windows "as it is" currently during
+ * a session. It may change during the session due to creation and destruction of windows.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ * @version 1.0
+ */
+public class WindowTree {
+
+    /**
+     * <p>
+     * Maintains a set of all the targets of all widgets that were at some point part of the
+     * window tree.
+     * </p>
+     */
+    private Set<MFCGUIElementSpec> targets;
+
+    /**
+     * <p>
+     * Map of all GUI element specifications that are part of the tree for efficient searching.
+     * The keys of the map are the hwnd's of the GUI elements.
+     * </p>
+     */
+    private Map<Long, MFCGUIElementSpec> guiElementSpecs;
+
+    /**
+     * <p>
+     * Map of all children of GUI elements that are part of the tree. The keys of the map are
+     * the hwnd's of the parent GUI elements.
+     * </p>
+     */
+    private Map<Long, List<MFCGUIElementSpec>> childRelations;
+
+    /**
+     * <p>
+     * Map of all parents of GUI elements that are part of the tree. The keys of the map are
+     * the hwnd's of the child GUI elements.
+     * </p>
+     */
+    private Map<Long, MFCGUIElementSpec> parentRelations;
+
+    /**
+     * <p>
+     * the internally created GUI model
+     * </p>
+     */
+    private GUIModel guiModel = new GUIModel();
+    
+    /**
+     * <p>
+     * the GUI element factory used in the model
+     * </p>
+     */
+    private IGUIElementFactory guiElementFactory = GUIElementFactory.getInstance();
+
+    /**
+     * <p>
+     * Map of all GUI elements that are part of the tree for efficient searching. The keys of the
+     * map are the hwnd's of the GUI elements.
+     * </p>
+     */
+    private Map<Long, MFCGUIElement> guiElements;
+
+    /**
+     * <p>
+     * Creates a new WindowTree.
+     * </p>
+     * <p>
+     * Private, as the class is a singleton.
+     * </p>
+     */
+    public WindowTree() {
+        guiElementSpecs = new HashMap<Long, MFCGUIElementSpec>();
+        targets = new HashSet<MFCGUIElementSpec>();
+        childRelations = new HashMap<Long, List<MFCGUIElementSpec>>();
+        parentRelations = new HashMap<Long, MFCGUIElementSpec>();
+        guiElements = new HashMap<Long, MFCGUIElement>();
+    }
+
+    /**
+     * <p>
+     * Adds a new window to the tree.
+     * </p>
+     * 
+     * @param parentHwnd
+     *            hwnd of the parent window
+     * @param childHwnd
+     *            hwnd of the window to be created
+     * @param childWindowName
+     *            resource id of the window to be created
+     * @param resourceId
+     *            resource id of the window to be created
+     * @param className
+     *            class name of the window to be created
+     */
+    public void add(long    parentHwnd,
+                    long    childHwnd,
+                    String  childWindowName,
+                    int     resourceId,
+                    String  className,
+                    boolean isModal)
+    {
+        MFCGUIElementSpec parent = guiElementSpecs.get(parentHwnd);
+        MFCGUIElementSpec child = guiElementSpecs.get(childHwnd);
+        if (child == null) {
+            child =
+                new MFCGUIElementSpec(childHwnd, childWindowName, resourceId, className, isModal);
+            if (parent != null) {
+                List<MFCGUIElementSpec> otherChildren = childRelations.get(parentHwnd);
+                
+                if (otherChildren == null) {
+                    otherChildren = new ArrayList<MFCGUIElementSpec>();
+                    childRelations.put(parentHwnd, otherChildren);
+                }
+                
+                otherChildren.add(child);
+                
+                parentRelations.put(childHwnd, parent);
+            }
+            guiElementSpecs.put(childHwnd, child);
+            targets.add(child);
+        }
+    }
+
+    /**
+     * <p>
+     * Searches the tree for a window with the specified hwnd and returns its {@link MFCGUIElementSpec}
+     * .
+     * </p>
+     * 
+     * @param hwnd
+     *            hwnd that is looked for
+     * @return {@link MFCGUIElementSpec} of the window with the given hwnd if found, null otherwise
+     */
+    public MFCGUIElement find(long hwnd) {
+        MFCGUIElement guiElement = guiElements.get(hwnd);
+        if (guiElement == null) {
+            List<MFCGUIElementSpec> guiElementPath = new ArrayList<MFCGUIElementSpec>();
+            
+            MFCGUIElementSpec child = guiElementSpecs.get(hwnd);
+            
+            if (child == null) {
+                throw new RuntimeException("no GUI element found with id " + hwnd);
+            }
+            
+            while (child != null) {
+                guiElementPath.add(0, child);
+                child = parentRelations.get(child.getHwnd());
+            }
+            
+            try {
+                guiElement = (MFCGUIElement)
+                    guiModel.integratePath(guiElementPath, guiElementFactory);
+            }
+            catch (GUIModelException e) {
+                throw new RuntimeException("could not instantiate GUI element with id " + hwnd, e);
+            }
+            guiElements.put(hwnd, guiElement);
+        }
+        return guiElement;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param hwnd
+     * @param windowName
+     */
+    public void setName(long hwnd, String windowName) {
+        MFCGUIElementSpec child = guiElementSpecs.get(hwnd);
+        if (child != null) {
+            child.setName(windowName);
+
+            MFCGUIElement guiElement = guiElements.remove(hwnd);
+            if (guiElement == null) {
+                // we need to update the GUI model as well
+                find(hwnd);
+            }
+        }
+    }
+    
+    /**
+     * <p>
+     * Removes a window (defined by its hwnd) from the tree. All children of the window will be
+     * removed recursively.
+     * </p>
+     * 
+     * @param hwnd
+     *            hwnd of the window to be removed
+     * @return number of windows that were removed
+     */
+    public int remove(long hwnd) {
+        MFCGUIElementSpec node = guiElementSpecs.remove(hwnd);
+        int removedCounter = 1;
+        
+        if (node != null) {
+            List<MFCGUIElementSpec> nodesToBeRemoved = childRelations.remove(hwnd);
+            
+            // remove all children and sub-children, if any
+            if (nodesToBeRemoved != null) {
+                for (int i = 0; i < nodesToBeRemoved.size(); i++) {
+                    MFCGUIElementSpec nodeToBeRemoved = nodesToBeRemoved.get(i);
+                    List<MFCGUIElementSpec> children =
+                        childRelations.remove(nodeToBeRemoved.getHwnd());
+                    
+                    if (children != null) {
+                        nodesToBeRemoved.addAll(children);
+                    }
+                    
+                    guiElementSpecs.remove(nodeToBeRemoved.getHwnd());
+                    parentRelations.remove(nodeToBeRemoved.getHwnd());
+                    removedCounter++;
+                }
+            }
+
+            // the node may be a child node of a parent. So search for it and remove it
+            MFCGUIElementSpec parent = parentRelations.remove(hwnd);
+            if (parent != null) {
+                List<MFCGUIElementSpec> children = childRelations.get(parent.getHwnd());
+
+                if (children != null) {
+                    for (int i = 0; i < children.size(); i++) {
+                        if (children.get(i).getHwnd() == hwnd) {
+                            children.remove(i);
+                            break;
+                        }
+                    }
+                    
+                    if (children.size() <= 0) {
+                        childRelations.remove(parent.getHwnd());
+                    }
+                }
+            }
+        }
+        return removedCounter;
+    }
+
+    /**
+     * @return the guiModel
+     */
+    public GUIModel getGUIModel() {
+        return guiModel;
+    }
+
+    /**
+     * <p>
+     * Returns the number of nodes contained in the WindowTree.
+     * </p>
+     * 
+     * @return number of nodes
+     */
+    public int size() {
+        return guiElementSpecs.size();
+    }
+
+    /**
+     * <p>
+     * Returns a sorted set of all targets that existed any time in the window tree.
+     * </p>
+     * 
+     * @return set of targets
+     */
+    public Set<MFCGUIElementSpec> getTargets() {
+        return targets;
+    }
+
+}
