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
RevLine 
[1002]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 {
[1004]41        /* Note that in the current version the id of a GUI element is assumed to be a long. For future
[1002]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
[1004]47     * map are the ids of the GUI elements.
[1002]48     * </p>
49     */
[1004]50    private Map<Long, IGUIElement> guiElements;
[1002]51
52    /**
53     * <p>
54     * Map of all GUI element specifications that are part of the tree for efficient searching. The
[1004]55     * keys of the map are the ids of the GUI elements.
[1002]56     * </p>
57     */
[1004]58    private Map<Long, IGUIElementSpec> guiElementSpecs;
[1002]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
[1004]63     * ids of the parent GUI elements.
[1002]64     * </p>
65     */
[1004]66    private Map<Long, List<Long>> childRelations;
[1002]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
[1004]71     * ids of the child GUI elements.
[1002]72     * </p>
73     */
[1004]74    private Map<Long, Long> parentRelations;
[1002]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() {
[1004]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>();
[1002]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){
[1004]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>();
[1002]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     */
[1004]131    public void add(Long guiElementID,
132                                Long parentID,
[1002]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) {
[1004]140                List<Long> otherChildren = childRelations.get(parentID);
[1002]141
142                if (otherChildren == null) {
[1004]143                    otherChildren = new ArrayList<Long>();
[1002]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
[1004]155            Long currentElementID = guiElementID;
[1002]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
[1025]175     * {@link IGUIElement} .
[1002]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     */
[1004]182    public IGUIElement find(long id) {
[1025]183        return guiElements.get(id);
[1002]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     */
[1004]196    public int remove(long id) {
[1005]197        int removedCounter = 0;
[1002]198        IGUIElementSpec node = guiElementSpecs.remove(id);
199
200        if (node != null) {
[1005]201                removedCounter++;
[1004]202            List<Long> nodesToBeRemoved = childRelations.remove(id);
[1002]203
204            // remove all children and sub-children, if any
205            if (nodesToBeRemoved != null) {
206                for (int i = 0; i < nodesToBeRemoved.size(); i++) {
[1004]207                    Long nodeToBeRemoved = nodesToBeRemoved.get(i);
208                    List<Long> children =
[1002]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 */
[1004]223            Long parent = parentRelations.remove(id);
[1002]224            if (parent != null) {
[1004]225                List<Long> children = childRelations.get(parent);
[1002]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.