source: trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/GUIElementTree.java @ 1025

Last change on this file since 1025 was 1025, checked in by fglaser, 12 years ago
  • Removed an inconsistency in GUIElementTree: find(...) does not throw exceptions if element was not found, but instead returns null.
  • Property svn:mime-type set to text/plain
File size: 8.3 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.eventcore.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 the interfaces for GUI element trees.
30 * </p>
31 * <p>
32 * The GUIElementTree represents the hierarchical structure of the GUI elements "as it is" currently during
33 * a session. It may change during the session due to creation and destruction of GUI elements.
34 * </p>
35 *
36 * @author Fabian Glaser
37 * @author Steffen Herbold
38 * @version 1.0
39 */
40public class GUIElementTree {
41        /* Note that in the current version the id of a GUI element is assumed to be a long. For future
42        versions it might be more suitable to change to some generic id type. */
43       
44         /**
45     * <p>
46     * Map of all GUI elements that are part of the tree for efficient searching. The keys of the
47     * map are the ids of the GUI elements.
48     * </p>
49     */
50    private Map<Long, IGUIElement> guiElements;
51
52    /**
53     * <p>
54     * Map of all GUI element specifications that are part of the tree for efficient searching. The
55     * keys of the map are the ids of the GUI elements.
56     * </p>
57     */
58    private Map<Long, IGUIElementSpec> guiElementSpecs;
59
60    /**
61     * <p>
62     * Map of all children of GUI elements that are part of the tree. The keys of the map are the
63     * ids of the parent GUI elements.
64     * </p>
65     */
66    private Map<Long, List<Long>> childRelations;
67
68    /**
69     * <p>
70     * Map of all parents of GUI elements that are part of the tree. The keys of the map are the
71     * ids of the child GUI elements.
72     * </p>
73     */
74    private Map<Long, Long> parentRelations;
75
76    /**
77     * <p>
78     * the internally created GUI model
79     * </p>
80     */
81    private GUIModel guiModel;
82
83    /**
84     * <p>
85     * the GUI element factory used in the model
86     * </p>
87     */
88    private IGUIElementFactory guiElementFactory = GUIElementFactory.getInstance();
89
90 
91
92    /**
93     * <p>
94     * Creates a new GUIElementTree.
95     * </p>
96     */
97    public GUIElementTree() {
98        guiElementSpecs = new HashMap<Long, IGUIElementSpec>();
99        childRelations = new HashMap<Long, List<Long>>();
100        parentRelations = new HashMap<Long, Long>();
101        guiElements = new HashMap<Long, IGUIElement>();
102        guiModel = new GUIModel();
103    }
104   
105    /**
106     * <p>
107     * Creates a GUIElementTree with an already existing guiModel
108     * @param guiModel
109     * </p>
110     */
111    public GUIElementTree(GUIModel guiModel){
112        guiElementSpecs = new HashMap<Long, IGUIElementSpec>();
113        childRelations = new HashMap<Long, List<Long>>();
114        parentRelations = new HashMap<Long, Long>();
115        guiElements = new HashMap<Long, IGUIElement>();
116        this.guiModel = guiModel;
117    }
118
119    /**
120     * <p>
121     * Adds a new GUI element to the tree.
122     * </p>
123     *
124     * @param guiElementID
125     *            id of the GUI element to be created
126     * @param parentID
127     *            id of the parent GUI element
128     * @param guiElementSpec
129     *                    the GUI element specification
130     */
131    public void add(Long guiElementID,
132                                Long parentID,
133                    IGUIElementSpec guiElementSpec)
134    {
135        IGUIElement guiElement = guiElements.get(guiElementID);
136       
137        if (guiElement == null) {
138                IGUIElementSpec parent = guiElementSpecs.get(parentID);
139            if (parent != null) {
140                List<Long> otherChildren = childRelations.get(parentID);
141
142                if (otherChildren == null) {
143                    otherChildren = new ArrayList<Long>();
144                    childRelations.put(parentID, otherChildren);
145                }
146
147                otherChildren.add(guiElementID);
148
149                parentRelations.put(guiElementID, parentID);
150            }
151            guiElementSpecs.put(guiElementID, guiElementSpec);
152           
153            List<IGUIElementSpec> guiElementPath = new ArrayList<IGUIElementSpec>();
154
155            Long currentElementID = guiElementID;
156            while (guiElementSpec != null) {
157                guiElementPath.add(0, guiElementSpec);
158                currentElementID = parentRelations.get(currentElementID);
159                guiElementSpec = guiElementSpecs.get(currentElementID);
160            }
161
162            try {
163                guiElement = guiModel.integratePath(guiElementPath, guiElementFactory);
164            }
165            catch (GUIModelException e) {
166                throw new RuntimeException("could not instantiate GUI element with id " + guiElementID, e);
167            }
168            guiElements.put(guiElementID, guiElement);
169        }
170    }
171
172    /**
173     * <p>
174     * Searches the tree for a GUI element with the specified id and returns its
175     * {@link IGUIElement} .
176     * </p>
177     *
178     * @param id
179     *            id that is looked for
180     * @return {@link IGUIElementSpec} of the GUI element with the given id if found, null otherwise
181     */
182    public IGUIElement find(long id) {
183        return guiElements.get(id);
184    }
185
186    /**
187     * <p>
188     * Removes a GUI element (defined by its id) from the tree. All children of the GUI element will be
189     * removed recursively.
190     * </p>
191     *
192     * @param id
193     *            id of the GUI element to be removed
194     * @return number of GUI elements that were removed
195     */
196    public int remove(long id) {
197        int removedCounter = 0;
198        IGUIElementSpec node = guiElementSpecs.remove(id);
199
200        if (node != null) {
201                removedCounter++;
202            List<Long> nodesToBeRemoved = childRelations.remove(id);
203
204            // remove all children and sub-children, if any
205            if (nodesToBeRemoved != null) {
206                for (int i = 0; i < nodesToBeRemoved.size(); i++) {
207                    Long nodeToBeRemoved = nodesToBeRemoved.get(i);
208                    List<Long> children =
209                        childRelations.remove(nodeToBeRemoved);
210
211                    if (children != null) {
212                        nodesToBeRemoved.addAll(children);
213                    }
214
215                    guiElementSpecs.remove(nodeToBeRemoved);
216                    parentRelations.remove(nodeToBeRemoved);
217                    removedCounter++;
218                }
219            }
220
221            /* the node may be a child node of a parent. So search for it in the child relations
222            of the parent and remove it */
223            Long parent = parentRelations.remove(id);
224            if (parent != null) {
225                List<Long> children = childRelations.get(parent);
226
227                if (children != null) {
228                    for (int i = 0; i < children.size(); i++) {
229                        if (children.get(i) == id) {
230                            children.remove(i);
231                            break;
232                        }
233                    }
234
235                    if (children.size() <= 0) {
236                        childRelations.remove(parent);
237                    }
238                }
239            }
240        }
241        return removedCounter;
242    }
243
244    /**
245     * @return the guiModel
246     */
247    public GUIModel getGUIModel() {
248        return guiModel;
249    }
250
251    /**
252     * <p>
253     * Returns the number of nodes contained in the JFCComponentTree.
254     * </p>
255     *
256     * @return number of nodes
257     */
258    public int size() {
259        return guiElementSpecs.size();
260    }
261
262}
Note: See TracBrowser for help on using the repository browser.