source: trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/guimodel/JFCComponentTree.java @ 966

Last change on this file since 966 was 965, checked in by fglaser, 12 years ago
  • Corrected bug in JFCSimplifiedLogParser and JFCComponentTree, which were using Long instead of Integers as hashCodes
  • Property svn:mime-type set to text/plain
File size: 9.4 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.plugin.jfc.guimodel;
16
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.List;
20import java.util.Map;
21
22import de.ugoe.cs.autoquest.eventcore.guimodel.GUIElementFactory;
23import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel;
24import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModelException;
25import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementFactory;
26
27/**
28 * <p>
29 * This class provides an the interfaces for component trees.
30 * </p>
31 * <p>
32 * The component tree represents the hierarchical structure of the components "as it is" currently during
33 * a session. It may change during the session due to creation and destruction of components.
34 * </p>
35 *
36 * @author Steffen Herbold
37 * @author Fabian Glaser
38 * @version 1.0
39 */
40public class JFCComponentTree {
41
42    /**
43     * <p>
44     * Map of all GUI element specifications that are part of the tree for efficient searching. The
45     * keys of the map are the hash values of the GUI elements.
46     * </p>
47     */
48    private Map<Integer, JFCGUIElementSpec> guiElementSpecs;
49
50    /**
51     * <p>
52     * Map of all children of GUI elements that are part of the tree. The keys of the map are the
53     * hash values of the parent GUI elements.
54     * </p>
55     */
56    private Map<Integer, List<JFCGUIElementSpec>> childRelations;
57
58    /**
59     * <p>
60     * Map of all parents of GUI elements that are part of the tree. The keys of the map are the
61     * hash values of the child GUI elements.
62     * </p>
63     */
64    private Map<Integer, JFCGUIElementSpec> parentRelations;
65
66    /**
67     * <p>
68     * the internally created GUI model
69     * </p>
70     */
71    private GUIModel guiModel = new GUIModel();
72
73    /**
74     * <p>
75     * the GUI element factory used in the model
76     * </p>
77     */
78    private IGUIElementFactory guiElementFactory = GUIElementFactory.getInstance();
79
80    /**
81     * <p>
82     * Map of all GUI elements that are part of the tree for efficient searching. The keys of the
83     * map are the hash values of the GUI elements.
84     * </p>
85     */
86    private Map<Integer, JFCGUIElement> guiElements;
87
88    /**
89     * <p>
90     * Creates a new JFCComponentTree.
91     * </p>
92     */
93    public JFCComponentTree() {
94        guiElementSpecs = new HashMap<Integer, JFCGUIElementSpec>();
95        childRelations = new HashMap<Integer, List<JFCGUIElementSpec>>();
96        parentRelations = new HashMap<Integer, JFCGUIElementSpec>();
97        guiElements = new HashMap<Integer, JFCGUIElement>();
98    }
99
100    /**
101     * <p>
102     * Adds a new component to the tree.
103     * </p>
104     *
105     * @param componentHash
106     *            hash of the window to be created
107     * @param parentHash
108     *            hash of the parent window
109     * @param componentSpec
110     *                    the component specification
111     */
112    public void add(Integer componentHash,
113                                Integer parentHash,
114                    JFCGUIElementSpec componentSpec)
115    {
116        JFCGUIElement guiElement = guiElements.get(componentHash);
117       
118        if (guiElement == null) {
119                JFCGUIElementSpec parent = guiElementSpecs.get(parentHash);
120            if (parent != null) {
121                List<JFCGUIElementSpec> otherChildren = childRelations.get(parentHash);
122
123                if (otherChildren == null) {
124                    otherChildren = new ArrayList<JFCGUIElementSpec>();
125                    childRelations.put(parentHash, otherChildren);
126                }
127
128                otherChildren.add(componentSpec);
129
130                parentRelations.put(componentHash, parent);
131            }
132            guiElementSpecs.put(componentHash, componentSpec);
133           
134            List<JFCGUIElementSpec> guiElementPath = new ArrayList<JFCGUIElementSpec>();
135
136            while (componentSpec != null) {
137                guiElementPath.add(0, componentSpec);
138                componentSpec = parentRelations.get(componentSpec.getElementHash());
139            }
140
141            try {
142                guiElement =
143                    (JFCGUIElement) guiModel.integratePath(guiElementPath, guiElementFactory);
144            }
145            catch (GUIModelException e) {
146                throw new RuntimeException("could not instantiate GUI element with id " + componentHash, e);
147            }
148            guiElements.put(componentHash, guiElement);
149        }
150    }
151
152    /**
153     * <p>
154     * Searches the tree for a component with the specified hash and returns its
155     * {@link JFCGUIElementSpec} .
156     * </p>
157     *
158     * @param hash
159     *            hash that is looked for
160     * @return {@link JFCGUIElementSpec} of the window with the given hash if found, null otherwise
161     */
162    public JFCGUIElement find(int hash) {
163        JFCGUIElement guiElement = guiElements.get(hash);
164        if (guiElement == null) {
165            List<JFCGUIElementSpec> guiElementPath = new ArrayList<JFCGUIElementSpec>();
166
167            JFCGUIElementSpec child = guiElementSpecs.get(hash);
168
169            if (child == null) {
170                throw new RuntimeException("no GUI element found with hash " + hash);
171            }
172
173            while (child != null) {
174                guiElementPath.add(0, child);
175                child = parentRelations.get(child.getElementHash());
176            }
177
178            try {
179                guiElement =
180                    (JFCGUIElement) guiModel.integratePath(guiElementPath, guiElementFactory);
181            }
182            catch (GUIModelException e) {
183                throw new RuntimeException("could not instantiate GUI element with id " + hash, e);
184            }
185            guiElements.put(hash, guiElement);
186        }
187        return guiElement;
188    }
189
190    /**
191     * <p>
192     * Sets the name of a GUI element given its hash.
193     * </p>
194     *
195     * @param hash
196     *            hash of the GUI element
197     * @param windowName
198     *            new name of the GUI element
199     */
200    public void setName(int hash, String windowName) {
201        JFCGUIElementSpec child = guiElementSpecs.get(hash);
202        if (child != null) {
203            child.setName(windowName);
204
205            JFCGUIElement guiElement = guiElements.remove(hash);
206            if (guiElement == null) {
207                // we need to update the GUI model as well
208                find(hash);
209            }
210        }
211    }
212
213    /**
214     * <p>
215     * Removes a window (defined by its hash) from the tree. All children of the window will be
216     * removed recursively.
217     * </p>
218     *
219     * @param hash
220     *            hash of the window to be removed
221     * @return number of windows that were removed
222     */
223    public int remove(long hash) {
224        JFCGUIElementSpec node = guiElementSpecs.remove(hash);
225        int removedCounter = 1;
226
227        if (node != null) {
228            List<JFCGUIElementSpec> nodesToBeRemoved = childRelations.remove(hash);
229
230            // remove all children and sub-children, if any
231            if (nodesToBeRemoved != null) {
232                for (int i = 0; i < nodesToBeRemoved.size(); i++) {
233                    JFCGUIElementSpec nodeToBeRemoved = nodesToBeRemoved.get(i);
234                    List<JFCGUIElementSpec> children =
235                        childRelations.remove(nodeToBeRemoved.getElementHash());
236
237                    if (children != null) {
238                        nodesToBeRemoved.addAll(children);
239                    }
240
241                    guiElementSpecs.remove(nodeToBeRemoved.getElementHash());
242                    parentRelations.remove(nodeToBeRemoved.getElementHash());
243                    removedCounter++;
244                }
245            }
246
247            // the node may be a child node of a parent. So search for it and remove it
248            JFCGUIElementSpec parent = parentRelations.remove(hash);
249            if (parent != null) {
250                List<JFCGUIElementSpec> children = childRelations.get(parent.getElementHash());
251
252                if (children != null) {
253                    for (int i = 0; i < children.size(); i++) {
254                        if (children.get(i).getElementHash() == hash) {
255                            children.remove(i);
256                            break;
257                        }
258                    }
259
260                    if (children.size() <= 0) {
261                        childRelations.remove(parent.getElementHash());
262                    }
263                }
264            }
265        }
266        return removedCounter;
267    }
268
269    /**
270     * @return the guiModel
271     */
272    public GUIModel getGUIModel() {
273        return guiModel;
274    }
275
276    /**
277     * <p>
278     * Returns the number of nodes contained in the JFCComponentTree.
279     * </p>
280     *
281     * @return number of nodes
282     */
283    public int size() {
284        return guiElementSpecs.size();
285    }
286
287}
Note: See TracBrowser for help on using the repository browser.