Index: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/WindowTree.java
===================================================================
--- trunk/quest-ui-core/src/main/java/de/ugoe/cs/quest/plugin/mfc/eventcore/WindowTree.java	(revision 488)
+++ trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/WindowTree.java	(revision 619)
@@ -1,9 +1,17 @@
-package de.ugoe.cs.quest.plugin.mfc.eventcore;
-
+
+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.SortedSet;
-import java.util.TreeSet;
+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;
+
 
 /**
@@ -12,15 +20,6 @@
  * </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.
+ * 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>
  * 
@@ -30,159 +29,262 @@
 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;
-	}
+    /**
+     * <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;
+    }
+
 }
