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

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