Changeset 2146 for trunk/autoquest-core-events/src
- Timestamp:
- 05/19/17 11:31:29 (8 years ago)
- Location:
- trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore
- Files:
-
- 7 added
- 2 deleted
- 8 edited
- 1 copied
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/EventTargetModelException.java
r2120 r2146 13 13 // limitations under the License. 14 14 15 package de.ugoe.cs.autoquest.eventcore .guimodel;15 package de.ugoe.cs.autoquest.eventcore; 16 16 17 17 /** 18 18 * <p> 19 * Exception that is thrown if there are problems with the {@link GUIModel}.19 * Exception that is thrown if there are problems with the {@link IHierarchicalEventTargetModel}. 20 20 * </p> 21 21 * … … 23 23 * @author Patrick Harms 24 24 */ 25 public class GUIModelException extends Exception {25 public class EventTargetModelException extends Exception { 26 26 27 27 /** … … 34 34 /** 35 35 * <p> 36 * Constructor. Creates a new GUIModelException.36 * Constructor. Creates a new EventTargetModelException. 37 37 * </p> 38 38 */ 39 public GUIModelException() {39 public EventTargetModelException() { 40 40 super(); 41 41 } … … 43 43 /** 44 44 * <p> 45 * Constructor. Creates a new GUIModelException.45 * Constructor. Creates a new EventTargetModelException. 46 46 * </p> 47 47 * … … 49 49 * message of the exception 50 50 */ 51 public GUIModelException(String message) {51 public EventTargetModelException(String message) { 52 52 super(message); 53 53 } … … 55 55 /** 56 56 * <p> 57 * Constructor. Creates a new GUIModelException.57 * Constructor. Creates a new EventTargetModelException. 58 58 * </p> 59 59 * … … 61 61 * cause of the exception 62 62 */ 63 public GUIModelException(Throwable cause) {63 public EventTargetModelException(Throwable cause) { 64 64 super(cause); 65 65 } … … 67 67 /** 68 68 * <p> 69 * Constructor. Creates a new GUIModelException.69 * Constructor. Creates a new EventTargetModelException. 70 70 * </p> 71 71 * … … 75 75 * cause of the exception 76 76 */ 77 public GUIModelException(String message, Throwable cause) {77 public EventTargetModelException(String message, Throwable cause) { 78 78 super(message, cause); 79 79 } -
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/HierarchicalEventTargetGroup.java
r2120 r2146 13 13 // limitations under the License. 14 14 15 package de.ugoe.cs.autoquest.eventcore .guimodel;15 package de.ugoe.cs.autoquest.eventcore; 16 16 17 17 import java.util.Collections; … … 21 21 /** 22 22 * <p> 23 * This class is a dummy GUI element to represent groups of GUI elements. A group of GUI elements24 * can be integrated in any GUImodel using the method25 * {@link GUIModel#groupGUIElements(java.util.List, String)}. A group has the same behavior as26 * any other parent GUI element.23 * This class is a dummy hierarchical event target to represent groups of event targets. A group of 24 * event targets can be integrated in any hierarchical event target model using the method 25 * {@link HierarchicalEventTargetModel#groupEventTargets(List, String, IEventTargetFactory)}. A 26 * group has the same behavior as any other parent hierarchical event target. 27 27 * </p> 28 28 * 29 29 * @author Patrick Harms 30 30 */ 31 public class GUIElementGroup extends AbstractDefaultGUIElement {31 public class HierarchicalEventTargetGroup extends AbstractDefaultHierarchicalEventTarget { 32 32 33 33 /** … … 39 39 40 40 /** 41 * the list of grouped GUIElements41 * the list of grouped event targets 42 42 */ 43 private List<IGUIElement> groupedGUIElements = new LinkedList<IGUIElement>(); 43 private List<IHierarchicalEventTarget> groupedEventTargets = 44 new LinkedList<IHierarchicalEventTarget>(); 44 45 45 46 /** 46 47 * <p> 47 * instantiates a GUI element group with a name and its optional parent GUI element48 * instantiates an event target group with a name and its optional parent event target 48 49 * </p> 49 50 * 50 * @param groupName the name of the GUI element group51 * @param parent the optional parent GUI element of the group52 * @param guiModel the GUImodel to which the group will belong51 * @param groupName the name of the event target group 52 * @param parent the optional parent event target of the group 53 * @param eventTargetModel the event target model to which the group will belong 53 54 */ 54 public GUIElementGroup(String groupName, IGUIElement parent, GUIModel guiModel) { 55 public HierarchicalEventTargetGroup(String groupName, 56 IHierarchicalEventTarget parent, 57 HierarchicalEventTargetModel<?> eventTargetModel) 58 { 55 59 super(new GroupSpecification(groupName), parent); 56 super.setGUIModel(guiModel); 57 } 58 59 /* (non-Javadoc) 60 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#updateSpecification(IGUIElementSpec) 61 */ 62 @Override 63 public final void updateSpecification(IGUIElementSpec furtherSpec) { 64 // do nothing 60 super.setEventTargetModel(eventTargetModel); 65 61 } 66 62 … … 90 86 91 87 /* (non-Javadoc) 92 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getView()88 * @see IHierarchicalEventTarget#updateSpecification(IEventTargetSpec) 93 89 */ 94 90 @Override 95 public IGUIView getView() { 96 return null; 97 } 98 99 /* (non-Javadoc) 100 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getDistanceTo(IGUIElement) 101 */ 102 @Override 103 public double getDistanceTo(IGUIElement otherElement) { 104 if (equals(otherElement)) { 105 return 0.0; 106 } 107 else if (super.getParent() != null) { 108 return super.getParent().getDistanceTo(otherElement); 109 } 110 else { 111 return 1.0; 112 } 91 public void updateSpecification(IEventTargetSpec furtherSpec) { 92 // do nothing 113 93 } 114 94 115 95 /** 116 96 * <p> 117 * returns the list of GUI elements belonging to this group.97 * returns the list of event targets belonging to this group. 118 98 * </p> 119 99 * 120 * @return the GUI elements belonging to this group100 * @return the event targets belonging to this group 121 101 * 122 102 */ 123 public List<I GUIElement> getGroupedElements() {124 return Collections.unmodifiableList(grouped GUIElements);103 public List<IHierarchicalEventTarget> getGroupedEventTargets() { 104 return Collections.unmodifiableList(groupedEventTargets); 125 105 } 126 106 127 107 /** 128 108 * <p> 129 * allows adding a new GUI element to the group109 * allows adding a new event target to the group 130 110 * </p> 131 111 * 132 * @param guiElement the new member of the group112 * @param eventTarget the new member of the group 133 113 */ 134 void addToGroup(I GUIElement guiElement) {135 this.grouped GUIElements.add(guiElement);114 void addToGroup(IHierarchicalEventTarget eventTarget) { 115 this.groupedEventTargets.add(eventTarget); 136 116 } 137 117 138 118 /** 139 119 * <p> 140 * internally required GUI element specification for a GUI element group. This is just a wrapper141 * for a name of a GUI element group120 * internally required event target specification for an event target group. This is just a 121 * wrapper for a name of an event target group 142 122 * </p> 143 123 * 144 124 * @author Patrick Harms 145 125 */ 146 private static class GroupSpecification implements I GUIElementSpec {126 private static class GroupSpecification implements IEventTargetSpec { 147 127 148 128 /** … … 155 135 /** 156 136 * <p> 157 * the name of the GUI element group represented by this specification137 * the name of the event target group represented by this specification 158 138 * </p> 159 139 */ … … 174 154 175 155 /* (non-Javadoc) 176 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getType()156 * @see IEventTargetSpec#getSimilarity(IEventTargetSpec) 177 157 */ 178 158 @Override 179 public String getType() { 180 return "GUI element group"; 181 } 182 183 /* (non-Javadoc) 184 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getTypeHierarchy() 185 */ 186 @Override 187 public String[] getTypeHierarchy() { 188 return new String[] { getType() }; 189 } 190 191 /* (non-Javadoc) 192 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getSimilarity(IGUIElementSpec) 193 */ 194 @Override 195 public boolean getSimilarity(IGUIElementSpec other) { 159 public boolean getSimilarity(IEventTargetSpec other) { 196 160 return 197 161 (other instanceof GroupSpecification) && -
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/IEventTarget.java
r927 r2146 20 20 * <p> 21 21 * Common interface for event targets. An event target can, e.g., be an element of a GUI or Web 22 * server . A concrete event-driven software platform can define its event targets through the22 * server or VR. A concrete event-driven software platform can define its event targets through the 23 23 * implementation of this interface. 24 24 * </p> … … 47 47 */ 48 48 public String getStringIdentifier(); 49 49 50 } -
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/AbstractDefaultGUIElement.java
r1436 r2146 15 15 package de.ugoe.cs.autoquest.eventcore.guimodel; 16 16 17 import java.util.LinkedList; 18 import java.util.List; 17 import de.ugoe.cs.autoquest.eventcore.AbstractDefaultHierarchicalEventTarget; 19 18 20 19 /** … … 26 25 * @author Patrick Harms 27 26 */ 28 public abstract class AbstractDefaultGUIElement implements IGUIElement { 27 public abstract class AbstractDefaultGUIElement extends AbstractDefaultHierarchicalEventTarget 28 implements IGUIElement 29 { 29 30 30 31 /** … … 34 35 */ 35 36 public static final long serialVersionUID = 1L; 36 37 /**38 * <p>39 * Specification of the GUI element40 * </p>41 */42 private final IGUIElementSpec specification;43 44 /**45 * <p>46 * Reference to the parent element47 * </p>48 */49 private IGUIElement parent;50 51 /**52 * <p>53 * List of other GUI elements being equal to this54 * </p>55 */56 private List<AbstractDefaultGUIElement> equalGUIElements = null;57 37 58 38 /** … … 62 42 */ 63 43 private boolean usageObserved; 64 65 /**66 * <p>67 * the reference to the GUI model to which this GUI element belongs.68 * </p>69 */70 private GUIModel guiModel;71 72 /**73 * <p>74 * the hash code of this object75 * </p>76 */77 private int hashCode;78 44 79 45 /** … … 88 54 */ 89 55 public AbstractDefaultGUIElement(IGUIElementSpec specification, IGUIElement parent) { 90 this.specification = specification; 91 this.usageObserved = false; 92 setParent(parent); 93 94 if (specification != null) { 95 this.hashCode = specification.hashCode(); 96 } 97 else { 98 this.hashCode = 0; 99 } 100 } 101 102 /* 103 * (non-Javadoc) 104 * 105 * @see de.ugoe.cs.tasktree.guimodel.GUIElement#getSpecification() 106 */ 107 @Override 108 public IGUIElementSpec getSpecification() { 109 return specification; 110 } 111 112 /* 113 * (non-Javadoc) 114 * 115 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getParent() 116 */ 117 @Override 118 public IGUIElement getParent() { 119 return parent; 56 super(specification, parent); 120 57 } 121 58 … … 125 62 @Override 126 63 public GUIModel getGUIModel() { 127 return guiModel;64 return (GUIModel) super.getEventTargetModel(); 128 65 } 129 66 130 /* 131 * (non-Javadoc) 132 * 133 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#addEqualGUIElement(IGUIElement) 67 /* (non-Javadoc) 68 * @see de.ugoe.cs.autoquest.eventcore.AbstractDefaultHierarchicalEventTarget#getParent() 134 69 */ 135 70 @Override 136 public void addEqualGUIElement(IGUIElement equalElement) { 137 if (!(equalElement instanceof AbstractDefaultGUIElement)) { 138 throw new IllegalArgumentException 139 ("this implementation can only handle other AbstractDefaultGUIElements"); 140 } 141 142 AbstractDefaultGUIElement other = (AbstractDefaultGUIElement) equalElement; 143 144 synchronized (AbstractDefaultGUIElement.class) { 145 if (this.equalGUIElements == null) { 146 if (other.equalGUIElements == null) { 147 this.equalGUIElements = new LinkedList<AbstractDefaultGUIElement>(); 148 this.equalGUIElements.add(this); 149 this.equalGUIElements.add(other); 150 other.equalGUIElements = this.equalGUIElements; 151 other.hashCode = this.hashCode; 152 } 153 else { 154 addIfNotContained(other.equalGUIElements, this); 155 this.equalGUIElements = other.equalGUIElements; 156 this.hashCode = other.hashCode; 157 } 158 } 159 else { 160 if (other.equalGUIElements == null) { 161 addIfNotContained(this.equalGUIElements, other); 162 other.equalGUIElements = this.equalGUIElements; 163 other.hashCode = this.hashCode; 164 } 165 else if (this.equalGUIElements != other.equalGUIElements) { 166 this.equalGUIElements.addAll(other.equalGUIElements); 71 public IGUIElement getParent() { 72 return (IGUIElement) super.getParent(); 73 } 167 74 168 // we also have to set this new list for all other elements for which so 169 // far list2 was registered 170 for (AbstractDefaultGUIElement candidate : other.equalGUIElements) { 171 candidate.equalGUIElements = this.equalGUIElements; 172 candidate.hashCode = this.hashCode; 173 } 75 /* (non-Javadoc) 76 * @see de.ugoe.cs.autoquest.eventcore.AbstractDefaultHierarchicalEventTarget#getSpecification() 77 */ 78 @Override 79 public IGUIElementSpec getSpecification() { 80 return (IGUIElementSpec) super.getSpecification(); 81 } 174 82 175 other.equalGUIElements = this.equalGUIElements; 176 other.hashCode = this.hashCode; 177 } 178 // else 179 // in this case, both GUI elements should already be registered with the same 180 // lists. 181 } 182 } 83 /* (non-Javadoc) 84 * @see de.ugoe.cs.autoquest.eventcore.AbstractDefaultHierarchicalEventTarget#getEventTargetModel() 85 */ 86 @Override 87 public GUIModel getEventTargetModel() { 88 return (GUIModel) super.getEventTargetModel(); 183 89 } 184 90 … … 203 109 } 204 110 205 /*206 * (non-Javadoc)207 *208 * @see GUIElement#equals(GUIElement)209 */210 public final boolean equals(Object other) {211 // implement final, as GUI elements are all singletons and they equal only if they are the212 // same object or if they are in the list of equal GUI elements213 if (super.equals(other)) {214 return true;215 }216 else if (other instanceof AbstractDefaultGUIElement) {217 synchronized (AbstractDefaultGUIElement.class) {218 if (equalGUIElements != null) {219 for (IGUIElement candidate : equalGUIElements) {220 if (candidate == other) {221 return true;222 }223 }224 }225 }226 }227 228 return false;229 }230 231 /*232 * (non-Javadoc)233 *234 * @see java.lang.Object#hashCode()235 */236 @Override237 public final int hashCode() {238 // implement final, as GUI elements are all singletons and they equal only if they are the239 // same object. If there are several GUI element objects that represent the same GUI element240 // then they are stored in the list of equal elements. But at least their type is expected241 // to be equal, so return the hash code of the type.242 return hashCode;243 }244 245 /**246 * <p>247 * updates the parent node of this node if required due to model restructuring248 * </p>249 */250 void setParent(IGUIElement newParent) {251 synchronized (AbstractDefaultGUIElement.class) {252 // all equal GUI elements must have the same parent. Otherwise, they are not equal253 // anymore and we would have discrepancies on the return value of getParent() on254 // equal GUI elements.255 this.parent = newParent;256 if (equalGUIElements != null) {257 for (AbstractDefaultGUIElement candidate : equalGUIElements) {258 candidate.parent = newParent;259 }260 }261 }262 }263 264 /**265 * <p>266 * used to set the GUI model to which this GUI element belongs. Will be set automatically, if267 * used in combination with {@link GUIModel};268 * </p>269 *270 * @param guiModel271 */272 void setGUIModel(GUIModel guiModel) {273 this.guiModel = guiModel;274 }275 276 /**277 * <p>278 * Adds an {@link AbstractDefaultGUIElement} as equal to a list of279 * {@link AbstractDefaultGUIElement}s if and only if it is not already contained.280 * </p>281 *282 * @param equalElementsList283 * list of {@link AbstractDefaultGUIElement} to which the GUI element is added284 * @param guiElement285 * GUI element to be added286 */287 private void addIfNotContained(List<AbstractDefaultGUIElement> equalElementsList,288 AbstractDefaultGUIElement guiElement)289 {290 for (IGUIElement candidate : equalElementsList) {291 if (candidate == guiElement) {292 return;293 }294 }295 296 equalElementsList.add(guiElement);297 }298 299 111 } -
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/GUIElementFactory.java
r1796 r2146 25 25 import java.util.logging.Level; 26 26 27 import de.ugoe.cs.autoquest.eventcore.EventTargetModelConfigurationException; 28 import de.ugoe.cs.autoquest.eventcore.HierarchicalEventTargetModel; 29 import de.ugoe.cs.autoquest.eventcore.IEventTargetFactory; 30 import de.ugoe.cs.autoquest.eventcore.IEventTargetSpec; 31 import de.ugoe.cs.autoquest.eventcore.IHierarchicalEventTarget; 27 32 import de.ugoe.cs.util.console.Console; 28 33 … … 35 40 * @author Patrick Harms 36 41 */ 37 public class GUIElementFactory implements I GUIElementFactory {42 public class GUIElementFactory implements IEventTargetFactory { 38 43 39 44 /** … … 64 69 /** 65 70 * <p> 66 * A property mapping that defines towhich Java class is created given the type of the GUI71 * A property mapping that defines which Java class is created given the type of the GUI 67 72 * element found in the specification. 68 73 * </p> … … 71 76 72 77 73 /* 74 * (non-Javadoc) 75 * 76 * @see 77 * de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementFactory#instantiateGUIElement(de.ugoe.cs.autoquest 78 * .eventcore.guimodel.IGUIElementSpec, de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement) 79 */ 78 /* (non-Javadoc) 79 * @see IEventTargetFactory#instantiateEventTarget(IEventTargetSpec, IHierarchicalEventTarget) 80 */ 81 @SuppressWarnings("unchecked") 80 82 @Override 81 public IGUIElement instantiateGUIElement(IGUIElementSpec specification, IGUIElement parent) 82 throws GUIModelConfigurationException 83 public <T extends IHierarchicalEventTarget> T instantiateEventTarget(IEventTargetSpec specification, 84 T parent) 85 throws EventTargetModelConfigurationException 86 { 87 if (!(specification instanceof IGUIElementSpec)) { 88 throw new IllegalArgumentException("can only handle IGUIElementSpecs as specification"); 89 } 90 91 if ((parent != null) && !(parent instanceof IGUIElement)) { 92 throw new IllegalArgumentException("can only handle IGUIElements as parent"); 93 } 94 95 return (T) instantiateEventTarget((IGUIElementSpec) specification, (IGUIElement) parent); 96 } 97 98 99 /** 100 * concrete implementation of {@link #instantiateEventTarget(IEventTargetSpec, IHierarchicalEventTarget)} 101 */ 102 public IGUIElement instantiateEventTarget(IGUIElementSpec specification, 103 IGUIElement parent) 104 throws EventTargetModelConfigurationException 83 105 { 84 106 Properties mappings = getMappingsFromConfiguration(); … … 155 177 Console.traceln(Level.WARNING, "configured GUI element representing class " + 156 178 className + " can not be loaded."); 157 throw new GUIModelConfigurationException179 throw new EventTargetModelConfigurationException 158 180 ("configured GUI element representing class " + className + 159 181 " can not be loaded.", e); … … 162 184 Console.traceln(Level.WARNING, "configured GUI element representing class " + 163 185 className + " can not be instantiated due to security reasons."); 164 throw new GUIModelConfigurationException186 throw new EventTargetModelConfigurationException 165 187 ("configured GUI element representing class " + className + 166 188 " can not be instantiated due to security reasons.", e); … … 169 191 Console.traceln(Level.WARNING, "configured GUI element representing class " + 170 192 className + " does not provide an appropriate constructor."); 171 throw new GUIModelConfigurationException193 throw new EventTargetModelConfigurationException 172 194 ("configured GUI element representing class " + className + 173 195 " does not provide an appropriate constructor.", e); … … 177 199 className + " does not provide an appropriate constructor " + 178 200 "accepting the provided parameters."); 179 throw new GUIModelConfigurationException201 throw new EventTargetModelConfigurationException 180 202 ("configured GUI element representing class " + className + " does not " + 181 203 "provide an appropriate constructor accepting the provided parameters.", e); … … 184 206 Console.traceln(Level.WARNING, "configured GUI element representing class " + 185 207 className + " can not be instantiated."); 186 throw new GUIModelConfigurationException208 throw new EventTargetModelConfigurationException 187 209 ("configured GUI element representing class " + className + 188 210 " can not be instantiated.", e); … … 191 213 Console.traceln(Level.WARNING, "configured GUI element representing class " + 192 214 className + " can not be instantiated."); 193 throw new GUIModelConfigurationException215 throw new EventTargetModelConfigurationException 194 216 ("configured GUI element representing class " + className + 195 217 " can not be instantiated.", e); … … 198 220 Console.traceln(Level.WARNING, "configured GUI element representing class " + 199 221 className + " can not be instantiated."); 200 throw new GUIModelConfigurationException222 throw new EventTargetModelConfigurationException 201 223 ("configured GUI element representing class " + className + 202 224 " can not be instantiated.", e); … … 208 230 specification.getType() + " found. Please extend GUI element " + 209 231 "mapping files."); 210 throw new GUIModelConfigurationException232 throw new EventTargetModelConfigurationException 211 233 ("no class representing GUI elements of type " + specification.getType() + 212 234 " found. Please extend GUI element mapping files"); … … 214 236 215 237 return guiElement; 238 } 239 240 /* (non-Javadoc) 241 * @see IEventTargetFactory#instantiateGroup(String, IHierarchicalEventTarget, HierarchicalEventTargetModel) 242 */ 243 @SuppressWarnings("unchecked") 244 @Override 245 public <T extends IHierarchicalEventTarget> T instantiateGroup(String groupName, 246 T parent, 247 HierarchicalEventTargetModel<T> hierarchicalEventTargetModel) 248 { 249 if (!(hierarchicalEventTargetModel instanceof GUIModel)) { 250 throw new IllegalArgumentException("can only handle GUI elements as event targets"); 251 } 252 253 if (!(parent instanceof IGUIElement)) { 254 throw new IllegalArgumentException("can only handle GUI elements as event targets"); 255 } 256 257 return (T) new GUIElementGroup 258 (groupName, (IGUIElement) parent, (GUIModel) hierarchicalEventTargetModel); 216 259 } 217 260 … … 226 269 */ 227 270 private synchronized Properties getMappingsFromConfiguration() 228 throws GUIModelConfigurationException271 throws EventTargetModelConfigurationException 229 272 { 230 273 if (mappingsFromConfiguration != null) { … … 249 292 } 250 293 catch (FileNotFoundException e) { 251 throw new GUIModelConfigurationException( 252 "could not read mapping configuration file " + 253 mappingsFile, e); 294 throw new EventTargetModelConfigurationException 295 ("could not read mapping configuration file " + mappingsFile, e); 254 296 } 255 297 catch (IOException e) { 256 throw new GUIModelConfigurationException( 257 "could not read mapping configuration file " + 258 mappingsFile, e); 298 throw new EventTargetModelConfigurationException 299 ("could not read mapping configuration file " + mappingsFile, e); 259 300 } 260 301 finally { … … 272 313 } 273 314 else { 274 throw new GUIModelConfigurationException( 275 "no GUI mappings file provided in folder " + 276 mappingsFolder); 315 throw new EventTargetModelConfigurationException 316 ("no GUI mappings file provided in folder " + mappingsFolder); 277 317 } 278 318 -
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/GUIElementGroup.java
- Property svn:mime-type set to text/plain
r1876 r2146 1 // Copyright 201 2Georg-August-Universität Göttingen, Germany1 // Copyright 2015 Georg-August-Universität Göttingen, Germany 2 2 // 3 3 // Licensed under the Apache License, Version 2.0 (the "License"); … … 15 15 package de.ugoe.cs.autoquest.eventcore.guimodel; 16 16 17 import java.util.Collections; 18 import java.util.LinkedList; 19 import java.util.List; 17 import de.ugoe.cs.autoquest.eventcore.HierarchicalEventTargetGroup; 18 import de.ugoe.cs.autoquest.eventcore.IEventTargetSpec; 20 19 21 20 /** 22 21 * <p> 23 * This class is a dummy GUI element to represent groups of GUI elements. A group of GUI elements 24 * can be integrated in any GUI model using the method 25 * {@link GUIModel#groupGUIElements(java.util.List, String)}. A group has the same behavior as 26 * any other parent GUI element. 22 * implementation of event target groups for GUI elements 27 23 * </p> 28 24 * 29 25 * @author Patrick Harms 30 26 */ 31 public class GUIElementGroup extends AbstractDefaultGUIElement {27 public class GUIElementGroup extends HierarchicalEventTargetGroup implements IGUIElement { 32 28 33 /** 34 * <p> 35 * default serial version UID 36 * </p> 37 */ 29 /** */ 38 30 private static final long serialVersionUID = 1L; 39 31 40 /** 41 * the list of grouped GUIElements 42 */ 43 private List<IGUIElement> groupedGUIElements = new LinkedList<IGUIElement>(); 32 /** the internal fake event target specification */ 33 private GroupSpecification groupSpecification; 34 35 /** stores if the usage of the group was observed (just to match the implemented interface */ 36 private boolean usageObserved = false; 44 37 45 38 /** … … 48 41 * </p> 49 42 * 50 * @param groupName the name of the GUI element group51 * @param parent the optional parent GUI element of the group52 * @param guiModelthe GUI model to which the group will belong43 * @param groupName the name of the GUI element group 44 * @param parent the optional parent GUI element of the group 45 * @param eventTargetModel the GUI model to which the group will belong 53 46 */ 54 public GUIElementGroup(String groupName, IGUIElement parent, GUIModel guiModel) { 55 super(new GroupSpecification(groupName), parent); 56 super.setGUIModel(guiModel); 47 public GUIElementGroup(String groupName, 48 IGUIElement parent, 49 GUIModel guiModel) 50 { 51 super(groupName, parent, guiModel); 52 groupSpecification = new GroupSpecification(groupName); 57 53 } 58 54 59 55 /* (non-Javadoc) 60 * @see de.ugoe.cs.autoquest.eventcore. guimodel.IGUIElement#updateSpecification(IGUIElementSpec)56 * @see de.ugoe.cs.autoquest.eventcore.AbstractDefaultHierarchicalEventTarget#getSpecification() 61 57 */ 62 58 @Override 63 public final void updateSpecification(IGUIElementSpec furtherSpec) { 64 // do nothing 65 } 66 67 /* (non-Javadoc) 68 * @see de.ugoe.cs.autoquest.eventcore.IEventTarget#getPlatform() 69 */ 70 @Override 71 public String getPlatform() { 72 return "none"; 59 public IGUIElementSpec getSpecification() { 60 return groupSpecification; 73 61 } 74 62 … … 78 66 @Override 79 67 public String getStringIdentifier() { 80 return ((GroupSpecification) super.getSpecification()).name;68 return groupSpecification.name; 81 69 } 82 70 83 71 /* (non-Javadoc) 84 * @see java.lang.Object#toString()72 * @see de.ugoe.cs.autoquest.eventcore.AbstractDefaultHierarchicalEventTarget#getParent() 85 73 */ 86 74 @Override 87 public String toString() {88 return getStringIdentifier();75 public IGUIElement getParent() { 76 return (IGUIElement) super.getParent(); 89 77 } 90 78 … … 98 86 99 87 /* (non-Javadoc) 88 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getGUIModel() 89 */ 90 @Override 91 public GUIModel getGUIModel() { 92 return (GUIModel) super.getEventTargetModel(); 93 } 94 95 /* (non-Javadoc) 96 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#isUsed() 97 */ 98 @Override 99 public boolean isUsed() { 100 return usageObserved; 101 } 102 103 /* (non-Javadoc) 104 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#markUsed() 105 */ 106 @Override 107 public void markUsed() { 108 usageObserved = true; 109 } 110 111 /* (non-Javadoc) 100 112 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getDistanceTo(IGUIElement) 101 113 */ … … 105 117 return 0.0; 106 118 } 107 else if ( super.getParent() != null) {108 return super.getParent().getDistanceTo(otherElement);119 else if (getParent() != null) { 120 return getParent().getDistanceTo(otherElement); 109 121 } 110 122 else { 111 123 return 1.0; 112 124 } 113 }114 115 /**116 * <p>117 * returns the list of GUI elements belonging to this group.118 * </p>119 *120 * @return the GUI elements belonging to this group121 *122 */123 public List<IGUIElement> getGroupedElements() {124 return Collections.unmodifiableList(groupedGUIElements);125 }126 127 /**128 * <p>129 * allows adding a new GUI element to the group130 * </p>131 *132 * @param guiElement the new member of the group133 */134 void addToGroup(IGUIElement guiElement) {135 this.groupedGUIElements.add(guiElement);136 125 } 137 126 … … 174 163 175 164 /* (non-Javadoc) 165 * @see de.ugoe.cs.autoquest.eventcore.IEventTargetSpec#getSimilarity(IEventTargetSpec) 166 */ 167 @Override 168 public boolean getSimilarity(IEventTargetSpec other) { 169 return 170 (other instanceof GroupSpecification) && 171 name.equals(((GroupSpecification) other).name); 172 } 173 174 /* (non-Javadoc) 176 175 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getType() 177 176 */ … … 189 188 } 190 189 191 /* (non-Javadoc)192 * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec#getSimilarity(IGUIElementSpec)193 */194 @Override195 public boolean getSimilarity(IGUIElementSpec other) {196 return197 (other instanceof GroupSpecification) &&198 name.equals(((GroupSpecification) other).name);199 }200 201 190 } 202 203 191 } -
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/GUIElementTree.java
r1084 r2146 20 20 import java.util.Map; 21 21 22 import de.ugoe.cs.autoquest.eventcore.EventTargetModelException; 23 import de.ugoe.cs.autoquest.eventcore.IEventTargetFactory; 22 24 import de.ugoe.cs.autoquest.eventcore.guimodel.GUIElementFactory; 23 25 import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel; 24 import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModelException;25 import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementFactory;26 26 27 27 /** … … 30 30 * </p> 31 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. 32 * The GUIElementTree represents the hierarchical structure of the GUI elements "as it is" 33 * currently during a session. It may change during the session due to creation and destruction 34 * of GUI elements. The parameter T represents the id type of the GUI elements that are handled 35 * internally. 35 36 * </p> 36 37 * … … 84 85 * </p> 85 86 */ 86 private IGUIElementFactory guiElementFactory = GUIElementFactory.getInstance(); 87 88 87 private IEventTargetFactory guiElementFactory = GUIElementFactory.getInstance(); 89 88 90 89 /** … … 127 126 * the GUI element specification 128 127 * 129 * @throws GUIModelException if the GUI element can not be added to the underlying GUI model128 * @throws EventTargetModelException if the GUI element can not be added to the underlying GUI model 130 129 */ 131 130 public void add(T guiElementID, 132 131 T parentID, 133 132 IGUIElementSpec guiElementSpec) 134 throws GUIModelException133 throws EventTargetModelException 135 134 { 136 135 IGUIElement guiElement = guiElements.get(guiElementID); … … 161 160 } 162 161 163 guiElement = guiModel.integratePath(guiElementPath, guiElementFactory);162 guiElement = (IGUIElement) guiModel.integratePath(guiElementPath, guiElementFactory); 164 163 guiElements.put(guiElementID, guiElement); 165 164 } -
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/GUIModel.java
- Property svn:mime-type set to text/plain
r1436 r2146 15 15 package de.ugoe.cs.autoquest.eventcore.guimodel; 16 16 17 import java.io.OutputStream;18 import java.io.PrintStream;19 17 import java.io.Serializable; 20 import java.io.UnsupportedEncodingException;21 import java.util.ArrayList;22 import java.util.HashMap;23 import java.util.LinkedList;24 18 import java.util.List; 25 import java.util.Map;26 import java.util.Stack;27 import java.util.logging.Level;28 19 29 import de.ugoe.cs. util.console.Console;20 import de.ugoe.cs.autoquest.eventcore.HierarchicalEventTargetModel; 30 21 31 22 /** … … 34 25 * platform independent. It may have several root nodes, as some GUIs are made up of several Frames 35 26 * being independent from each other. The GUI model is filled using the 36 * {@link #integratePath(List, IGUIElementFactory)} method.27 * {@link #integratePath(List, de.ugoe.cs.autoquest.eventcore.IEventTargetFactory)} method. 37 28 * </p> 38 29 * … … 40 31 * @author Patrick Harms, Steffen Herbold 41 32 */ 42 public class GUIModel implements Serializable { 33 public class GUIModel extends HierarchicalEventTargetModel<IGUIElement> 34 implements Serializable 35 { 43 36 44 37 /** */ … … 47 40 /** 48 41 * <p> 49 * The root node of the tree not provided externally. 50 * </p> 51 */ 52 private TreeNode root = new TreeNode(); 53 54 /** 55 * <p> 56 * A map with all nodes currently known 57 * </p> 58 */ 59 private Map<IGUIElement, TreeNode> allNodes = new HashMap<IGUIElement, TreeNode>(); 60 61 /** 62 * <p> 63 * true, if internal validation is switched on, false else 64 * </p> 65 */ 66 private boolean validate = false; 67 68 /** 69 * <p> 70 * Default constructor to create a GUI model without internal validation 42 * instantiate a default unvalidated model 71 43 * </p> 72 44 * 73 45 */ 74 46 public GUIModel() { 75 this(false);47 super(); 76 48 } 77 49 78 50 /** 79 51 * <p> 80 * creates a GUI model, that internally validates itself by checking on access to nodes, 81 * if several GUI elements pretend to be equal or if several distinct GUI elements have the 82 * same child. 52 * instantiate a model that will validate itself internally if the provided parameters is set 53 * to true. This is typically rather slow. 83 54 * </p> 84 *85 * @param validate86 * true if internal validation shall be switched on (bad performance), false else87 *88 55 */ 89 56 public GUIModel(boolean validate) { 90 this.validate = validate;57 super(validate); 91 58 } 92 59 93 /**94 * <p>95 * Integrates a path of GUI elements into the GUI model. The GUI model itself is a tree and96 * therefore a set of different paths through the tree that start with a root node and end with97 * a leaf node. Such a path can be added to the tree. The method checks, if any of the GUI98 * elements denoted by the path already exists. If so, it reuses it. It may therefore also99 * return an existing GUI element being the leaf node of the provided path. If a GUI element of100 * the path does not exist yet, it creates a new one using the provided GUI element factory.101 * </p>102 * <p>103 * If a GUI element specification describes an existing GUI element or not is determined through104 * comparing the GUI element specifications of the existing GUI elements with the ones provided105 * in the path. The comparison is done using the106 * {@link IGUIElementSpec#getSimilarity(IGUIElementSpec)} method. The comparison is only done on107 * the correct levels. I.e. the currently known root elements of the tree are only compared to108 * the first element in the path. If the correct one is found or created, its children are109 * compared only to the second specification in the path, and so on.110 * </p>111 * <p>112 * The returned GUI elements are singletons. I.e. it is tried to return always the identical113 * object for the same denoted element. However, while creating the GUI model, the similarity of114 * GUI elements may change. Therefore, the method might determine, that two formerly different115 * nodes are now similar. (This may happen, e.g. if GUI elements do not have initial names which116 * are set afterwards. Therefore, first they are handled differently and later they can be117 * identified as being the same.) In such a case, there are already several GUI element objects118 * instantiated for the same GUI element. The singleton paradigm gets broken. Therefore, such119 * GUI element objects are registered with each other, so that their equal method can determine120 * equality again correctly, although the objects are no singletons anymore.121 * </p>122 *123 * @param guiElementPath124 * the path to integrate into the model125 * @param guiElementFactory126 * the GUI element factory to be used for instantiating GUI element objects127 *128 * @return The GUI element object representing the GUI element denoted by the provided path129 *130 * @throws GUIModelException131 * thrown in cases such as the GUI element object could not be instantiated132 * @throws IllegalArgumentException133 * if the provided path is invalid.134 */135 public IGUIElement integratePath(List<? extends IGUIElementSpec> guiElementPath,136 IGUIElementFactory guiElementFactory)137 throws GUIModelException, IllegalArgumentException138 {139 if ((guiElementPath == null) || (guiElementPath.size() <= 0)) {140 throw new IllegalArgumentException("GUI element path must contain at least one element");141 }142 143 List<IGUIElementSpec> remainingPath = new LinkedList<IGUIElementSpec>(guiElementPath);144 145 return integratePath(root, remainingPath, guiElementFactory);146 }147 148 /**149 * <p>150 * Returns all children of the provided GUI element or null, if it does not have any or the node151 * is unknown.152 * </p>153 *154 * @param guiElement155 * the GUI element of which the children shall be returned156 *157 * @return As described158 */159 public List<IGUIElement> getChildren(IGUIElement guiElement) {160 TreeNode node = findNode(guiElement);161 162 List<IGUIElement> result = null;163 if (node != null) {164 result = new LinkedList<IGUIElement>();165 if (node.children != null) {166 for (TreeNode child : node.children) {167 result.add(child.guiElement);168 }169 }170 }171 else {172 System.out.println("problem");173 boolean found = false;174 for (Map.Entry<IGUIElement, TreeNode> entry : allNodes.entrySet()) {175 if (entry.getKey().equals(guiElement)) {176 if (!found) {177 System.out.println(guiElement.hashCode() + " " + entry.getKey().hashCode());178 found = true;179 }180 else {181 Console.traceln(Level.SEVERE, "Multiple nodes in the internal GUI model " +182 "match the same GUI element. This should not be the case " +183 "and the GUI model is probably invalid.");184 }185 }186 }187 188 if (!found) {189 Console.traceln(Level.SEVERE, "GUI element belonging to model not found in model");190 }191 }192 193 return result;194 }195 196 /**197 * <p>198 * Returns the parent GUI element of the provided GUI element or null, if it does not have a199 * parent (i.e. if it is a root node) or if the node is unknown.200 * </p>201 *202 * @param guiElement203 * the GUI element of which the parent shall be returned204 *205 * @return As described206 */207 public IGUIElement getParent(IGUIElement guiElement) {208 IGUIElement parent = null;209 210 for (Map.Entry<IGUIElement, TreeNode> entry : allNodes.entrySet()) {211 if (entry.getValue().children != null) {212 for (TreeNode child : entry.getValue().children) {213 if (child.guiElement.equals(guiElement)) {214 if (parent == null) {215 parent = entry.getKey();216 if (!validate) {217 break;218 }219 }220 else {221 Console222 .traceln(Level.SEVERE,223 "Multiple nodes in the internal GUI model match the same GUI element. "224 + "This should not be the case and the GUI model is probably invalid.");225 }226 }227 }228 }229 }230 231 return parent;232 }233 234 /**235 * <p>236 * Returns all root GUI elements of the model or an empty list, if the model is empty237 * </p>238 *239 * @return As described240 */241 public List<IGUIElement> getRootElements() {242 List<IGUIElement> roots = new ArrayList<IGUIElement>();243 244 if (root.children != null) {245 for (TreeNode rootChild : root.children) {246 roots.add(rootChild.guiElement);247 }248 }249 250 return roots;251 }252 253 /**254 * returns a traverser for the GUI model to have efficient access to the tree of GUI elements255 * without having direct access.256 *257 * @return a traverser258 */259 public Traverser getTraverser() {260 return new Traverser();261 }262 263 /**264 * returns a traverser for the GUI model starting at the given GUI element. Returns null, if265 * the GUI element is not part of the model.266 *267 * @return a traverser268 */269 public Traverser getTraverser(IGUIElement startingAt) {270 TreeNode node = findNode(startingAt);271 272 if (node != null) {273 Traverser traverser = new Traverser();274 traverser.navigateTo(node);275 return traverser;276 }277 else {278 return null;279 }280 }281 282 /**283 * <p>284 * dumps the GUI model to the provided stream. Each node is represented through its toString()285 * method. If a node has children, those are dumped indented and surrounded by braces.286 * </p>287 *288 * @param out289 * The stream to dump the textual representation of the model to290 * @param encoding291 * The encoding to be used while dumping292 */293 public void dump(OutputStream out, String encoding) {294 PrintStream stream;295 296 if (out instanceof PrintStream) {297 stream = (PrintStream) out;298 }299 else {300 String enc = encoding == null ? "UTF-8" : encoding;301 try {302 stream = new PrintStream(out, true, enc);303 }304 catch (UnsupportedEncodingException e) {305 throw new IllegalArgumentException("encodind " + enc + " not supported");306 }307 }308 309 for (TreeNode node : root.children) {310 dumpGUIElement(stream, node, "");311 }312 }313 314 /**315 * <p>316 * This method groups the provided GUI elements under a common parent GUI element. The current317 * parent GUI element of the GUI elements to group must be the same. If the GUI elements to318 * be grouped are the whole list of children of the same parent, nothing is changed.319 * </p>320 *321 * @param guiElements the list of GUI elements to be grouped322 * @param groupName the name of the GUI element group to be created323 *324 * @return the GUI element representing the group, or null, if the provided list of GUI elements325 * is empty326 *327 * @throws IllegalArgumentException328 * if not all GUI elements to be merged share the same parent, if one of the329 * parameters is null, or if one of the provided GUI elements does not belong to330 * the model331 */332 public IGUIElement groupGUIElements(List<IGUIElement> guiElements, String groupName)333 throws IllegalArgumentException334 {335 if ((guiElements == null) || (groupName == null)) {336 throw new IllegalArgumentException("parameters must not be null");337 }338 339 if (guiElements.size() <= 0) {340 // do nothing341 return null;342 }343 344 TreeNode parent = findNode(guiElements.get(0).getParent());345 if (parent == null) {346 throw new IllegalArgumentException("GUI elements to group must have a parent: parent " +347 "of " + guiElements.get(0) + " is " +348 guiElements.get(0).getParent() + " and not found " +349 "in the model");350 }351 352 List<TreeNode> nodesToGroup = new LinkedList<TreeNode>();353 354 for (IGUIElement element : guiElements) {355 if (!(element instanceof AbstractDefaultGUIElement)) {356 throw new IllegalArgumentException357 ("can only group nodes of type AbstractDefaultGUIElement");358 }359 360 TreeNode node = findNode(element);361 if (node == null) {362 throw new IllegalArgumentException363 ("GUI element " + element + " is not part of the model");364 }365 366 if (!nodesToGroup.contains(node)) {367 nodesToGroup.add(node);368 }369 370 TreeNode parentNode = findNode(element.getParent());371 372 if (!parent.equals(parentNode)) {373 throw new IllegalArgumentException("GUI elements do not share the same parent: " +374 parent + " (parent of " + guiElements.get(0) +375 ") <> " + parentNode + " (parent of " +376 element + ")");377 }378 }379 380 TreeNode replacement = new TreeNode();381 replacement.guiElement = new GUIElementGroup(groupName, parent.guiElement, this);382 383 for (TreeNode child : nodesToGroup) {384 ((GUIElementGroup) replacement.guiElement).addToGroup(child.guiElement);385 replacement.addChildNode(child);386 ((AbstractDefaultGUIElement) child.guiElement).setParent(replacement.guiElement);387 parent.children.remove(child);388 }389 390 parent.children.add(replacement);391 392 // finally, update the known nodes list393 // if you don't do this getChildren will return wrong things and very bad things happen!394 allNodes.put(replacement.guiElement, replacement);395 396 return replacement.guiElement;397 }398 399 /**400 * <p>401 * By calling this method, the GUIModel is traversed and similar nodes are merged.402 * </p>403 *404 */405 public void condenseModel() {406 mergeSubTree(root);407 }408 409 /**410 * <p>411 * Merges the tree nodes of two GUI elements. The GUI elements need to have the same parent.412 * They are merged recursively, i.e. also their children are merged.413 * </p>414 *415 * @param guiElement1416 * the first merge GUI element417 * @param guiElement2418 * the second merge GUI element419 *420 * @return the result of the merge421 *422 * @throws IllegalArgumentException423 * thrown if the two GUI elements do not have the same parent424 */425 public IGUIElement mergeGUIElements(IGUIElement guiElement1, IGUIElement guiElement2)426 throws IllegalArgumentException427 {428 return mergeGUIElements(guiElement1, guiElement2, true);429 }430 431 /**432 * <p>433 * Merges the tree nodes of two GUI elements. The GUI elements need to have the same parent.434 * If the <code>recursively</code> parameter is set to true, the children of the GUI elements435 * are merged, as well, as long as they are similar. If the parameter is false, the children436 * are not merged. In this case the resulting GUI element has all children of both merged GUI437 * elements.438 * </p>439 *440 * @param guiElement1441 * the first merge GUI element442 * @param guiElement2443 * the second merge GUI element444 * @param recursively445 * if true, the merge is done also for similar children, if false, not.446 *447 * @return the result of the merge448 *449 * @throws IllegalArgumentException450 * thrown if the two GUI elements do not have the same parent451 */452 public IGUIElement mergeGUIElements(IGUIElement guiElement1,453 IGUIElement guiElement2,454 boolean recursively)455 throws IllegalArgumentException456 {457 // check if both nodes have the same parent458 IGUIElement parentElement = guiElement1.getParent();459 boolean sameParent = (parentElement != null) ?460 parentElement.equals(guiElement2.getParent()) : (guiElement2.getParent() == null);461 462 if (!sameParent) {463 throw new IllegalArgumentException("can only merge nodes with the same parent");464 }465 466 // get the TreeNode of the parent of the GUI elements467 TreeNode parent = findNode(parentElement);468 469 if ((parent == null) && (parentElement == null)) {470 // merging root nodes. The parent is the root node of the GUI element tree471 parent = root;472 }473 474 // get the TreeNodes for both GUI elements475 TreeNode node1 = findNode(guiElement1);476 TreeNode node2 = findNode(guiElement2);477 478 if (node1 == null || node2 == null) {479 throw new IllegalArgumentException480 ("Error while merging nodes: one element is not part of the GUI model!");481 }482 483 TreeNode replacement = mergeTreeNodes(node1, node2, recursively);484 485 if (parent != null) {486 // remove node1 and node2 from the parent's children and add the replacement instead487 // assumes that there are no duplicates of node1 and node2488 if (parent.children != null) {489 parent.children.set(parent.children.indexOf(node1), replacement);490 parent.children.remove(node2);491 }492 }493 494 return replacement.guiElement;495 }496 497 /**498 * <p>499 * internally integrates a path as the children of the provided parent node. This method is500 * recursive and calls itself, for the child of the parent node, that matches the first element501 * in the remaining path.502 * </p>503 *504 * @param parentNode505 * the parent node to add children for506 * @param guiElementPath507 * the path of children to be created starting with the parent node508 * @param guiElementFactory509 * the GUI element factory to be used for instantiating GUI element objects510 *511 * @return The GUI element object representing the GUI element denoted by the provided path512 *513 * @throws GUIModelException514 * thrown in cases such as the GUI element object could not be instantiated515 */516 private IGUIElement integratePath(TreeNode parentNode,517 List<? extends IGUIElementSpec> remainingPath,518 IGUIElementFactory guiElementFactory)519 throws GUIModelException520 {521 IGUIElementSpec specToIntegrateElementFor = remainingPath.remove(0);522 523 TreeNode child = findEqualChild(parentNode, specToIntegrateElementFor);524 if (child == null) {525 IGUIElement newElement =526 guiElementFactory.instantiateGUIElement(specToIntegrateElementFor,527 parentNode.guiElement);528 529 if (newElement instanceof AbstractDefaultGUIElement) {530 ((AbstractDefaultGUIElement) newElement).setGUIModel(this);531 }532 533 child = parentNode.addChild(newElement);534 allNodes.put(child.guiElement, child);535 }536 537 if (remainingPath.size() > 0) {538 return integratePath(child, remainingPath, guiElementFactory);539 }540 else {541 return child.guiElement;542 }543 }544 545 /**546 * <p>547 * Searches the children of a tree node to see if the {@link IGUIElementSpec} of equals the548 * specification of the {@link TreeNode#guiElement} of the child. If a match is found, the child549 * is returned.550 * </p>551 *552 * @param parentNode553 * parent node whose children are searched554 * @param specToMatch555 * specification that is searched for556 * @return matching child node or null if no child matches557 */558 private TreeNode findEqualChild(TreeNode parentNode, IGUIElementSpec specToMatch) {559 if (parentNode.children != null) {560 for (TreeNode child : parentNode.children) {561 if (specToMatch.equals(child.guiElement.getSpecification())) {562 return child;563 }564 }565 }566 return null;567 }568 569 /**570 * <p>571 * Merges all similar nodes in the sub-tree of the GUI model defined by the subTreeRoot.572 * </p>573 * <p>574 * The merging order is a bottom-up. This means, that we first call mergeSubTree recursively for575 * the grand children of the subTreeRoot, before we merge subTreeRoot.576 * </p>577 * <p>578 * The merging strategy is top-down. This means, that every time we merge two child nodes, we579 * call mergeSubTree recursively for all children of the merged nodes in order to check if we580 * can merge the children, too.581 * </p>582 *583 * @param subTreeRoot584 * root node of the sub-tree that is merged585 */586 private void mergeSubTree(TreeNode subTreeRoot) {587 if (subTreeRoot.children == null || subTreeRoot.children.isEmpty()) {588 return;589 }590 591 // lets first merge the grand children of the parentNode592 for (TreeNode child : subTreeRoot.children) {593 mergeSubTree(child);594 }595 596 boolean performedMerge;597 598 do {599 performedMerge = false;600 for (int i = 0; !performedMerge && i < subTreeRoot.children.size(); i++) {601 IGUIElementSpec elemSpec1 =602 subTreeRoot.children.get(i).guiElement.getSpecification();603 for (int j = i + 1; !performedMerge && j < subTreeRoot.children.size(); j++) {604 IGUIElementSpec elemSpec2 =605 subTreeRoot.children.get(j).guiElement.getSpecification();606 if (elemSpec1.getSimilarity(elemSpec2)) {607 TreeNode replacement = mergeTreeNodes608 (subTreeRoot.children.get(i), subTreeRoot.children.get(j), true);609 610 subTreeRoot.children.set(i, replacement);611 subTreeRoot.children.remove(j);612 performedMerge = true;613 i--;614 break;615 }616 }617 }618 }619 while (performedMerge);620 }621 622 /**623 * <p>624 * merges two nodes with each other. Merging means registering the GUI element objects with each625 * other for equality checks. Further it adds all children of both nodes to a new replacing626 * node. Afterwards, all similar nodes of the replacement node are merged as well as long627 * the recursive parameter is set to true.628 * </p>629 *630 * @param treeNode1631 * the first of the two nodes to be merged632 * @param treeNode2633 * the second of the two nodes to be merged634 * @param recursively635 * if true, the merging also merges child nodes636 *637 * @return a tree node being the merge of the two provided nodes.638 */639 private TreeNode mergeTreeNodes(TreeNode treeNode1, TreeNode treeNode2, boolean recursively) {640 // and now a replacement node that is the merge of treeNode1 and treeNode2 is created641 TreeNode replacement = new TreeNode();642 replacement.guiElement = treeNode1.guiElement;643 if (treeNode1.children != null) {644 for (TreeNode child : treeNode1.children) {645 replacement.addChildNode(child);646 }647 }648 if (treeNode2.children != null) {649 for (TreeNode child : treeNode2.children) {650 replacement.addChildNode(child);651 }652 }653 654 if (recursively) {655 mergeSubTree(replacement);656 }657 658 replacement.guiElement.updateSpecification(treeNode2.guiElement.getSpecification());659 660 // finally, update the known nodes list661 // if you don't do this getChildren will return wrong things and very bad things happen!662 allNodes.remove(treeNode1.guiElement);663 allNodes.remove(treeNode2.guiElement);664 665 // the following two lines are needed to preserve the references to the existing GUI666 // elements. If two elements are the same, one should be deleted to make the elements667 // singletons again. However, there may exist references to both objects. To preserve668 // these, we simply register the equal GUI elements with each other so that an equals669 // check can return true.670 treeNode1.guiElement.addEqualGUIElement(treeNode2.guiElement);671 treeNode2.guiElement.addEqualGUIElement(treeNode1.guiElement);672 673 allNodes.put(replacement.guiElement, replacement);674 675 return replacement;676 }677 678 /**679 * <p>680 * dumps a GUI element to the stream. A dump contains the toString() representation of the GUI681 * element as well as a indented list of its children surrounded by braces. Therefore, not the682 * GUI element itself but its tree node is provided to have an efficient access to its children683 * </p>684 *685 * @param out686 * {@link PrintStream} where the guiElement is dumped to687 * @param node688 * the guiElement's tree node of which the string representation is dumped689 * @param indent690 * indent string of the dumping691 */692 private void dumpGUIElement(PrintStream out, TreeNode node, String indent) {693 out.print(indent);694 out.print(node.guiElement);695 696 if ((node.children != null) && (node.children.size() > 0)) {697 out.println(" {");698 699 for (TreeNode child : node.children) {700 dumpGUIElement(out, child, indent + " ");701 }702 703 out.print(indent);704 out.print("}");705 }706 707 out.println();708 }709 710 /**711 * <p>712 * Retrieves the TreeNode associated with a GUI element. Returns null if no such TreeNode is713 * found.714 * </p>715 *716 * @param element717 * the GUI element718 * @return associated TreeNode; null if no such node exists719 */720 private TreeNode findNode(IGUIElement element) {721 if (element == null) {722 return null;723 }724 725 TreeNode result = null;726 727 if (!validate) {728 result = allNodes.get(element);729 }730 else {731 for (Map.Entry<IGUIElement, TreeNode> entry : allNodes.entrySet()) {732 if (entry.getKey().equals(element)) {733 if (result == null) {734 result = entry.getValue();735 }736 else {737 Console.traceln(Level.SEVERE, "Multiple nodes in the internal GUI model " +738 "match the same GUI element. This should not be the case " +739 "and the GUI model is probably invalid.");740 }741 }742 }743 }744 return result;745 }746 747 /**748 * <p>749 * Used externally for tree traversal without providing direct access to the tree nodes750 * </p>751 *752 * @version 1.0753 * @author Patrick Harms, Steffen Herbold754 */755 public class Traverser {756 757 /**758 * <p>759 * the stack of nodes on which the traverser currently works760 * </p>761 */762 private Stack<StackEntry> nodeStack = new Stack<StackEntry>();763 764 /**765 * <p>766 * initializes the traverser by adding the root node of the GUI model to the stack767 * </p>768 */769 private Traverser() {770 nodeStack.push(new StackEntry(root, 0));771 }772 773 /**774 * <p>775 * returns the first child of the current GUI element. On the first call of this method on776 * the traverser the first of the root GUI elements of the GUI model is returned. If the777 * current GUI element does not have children, the method returns null. If the GUI model778 * is empty, then a call to this method will return null. The returned GUI element is the779 * next one the traverser points to.780 * </p>781 *782 * @return as described.783 */784 public IGUIElement firstChild() {785 return pushChild(0);786 }787 788 /**789 * <p>790 * returns true, if the current GUI element has a first child, i.e. if the next call to the791 * method {@link #firstChild()} would return a GUI element or null.792 * </p>793 *794 * @return as described795 */796 public boolean hasFirstChild() {797 return798 (nodeStack.peek().treeNode.children != null) &&799 (nodeStack.peek().treeNode.children.size() > 0);800 }801 802 /**803 * <p>804 * returns the next sibling of the current GUI element. If there is no further sibling,805 * null is returned. If the current GUI element is one of the root nodes, the next root806 * node of the GUI model is returned. The returned GUI element is the next one the807 * traverser points to.808 * </p>809 *810 * @return as described811 */812 public IGUIElement nextSibling() {813 int lastIndex = nodeStack.pop().index;814 815 IGUIElement retval = pushChild(lastIndex + 1);816 if (retval == null) {817 pushChild(lastIndex);818 }819 820 return retval;821 }822 823 /**824 * <p>825 * returns true, if the current GUI element has a further sibling, i.e. if a call to the826 * method {@link #nextSibling()} will return a GUI element;827 * </p>828 *829 * @return as described830 */831 public boolean hasNextSibling() {832 boolean result = false;833 if (nodeStack.size() > 1) {834 StackEntry entry = nodeStack.pop();835 result = nodeStack.peek().treeNode.children.size() > (entry.index + 1);836 pushChild(entry.index);837 }838 839 return result;840 }841 842 /**843 * <p>844 * returns the parent GUI element of the current GUI element. If the current GUI element845 * is a root node, null is returned. If there is no current GUI element yet as the method846 * {@link #firstChild()} was not called yet, null is returned.847 * </p>848 *849 * @return as described850 */851 public IGUIElement parent() {852 IGUIElement retval = null;853 854 if (nodeStack.size() > 1) {855 nodeStack.pop();856 retval = nodeStack.peek().treeNode.guiElement;857 }858 859 return retval;860 }861 862 /**863 * <p>864 * internal method used for changing the state of the traverser. I.e. to switch to a865 * specific child GUI element of the current one.866 * </p>867 */868 private IGUIElement pushChild(int index) {869 IGUIElement retVal = null;870 871 if ((nodeStack.peek().treeNode.children != null) &&872 (nodeStack.peek().treeNode.children.size() > index))873 {874 nodeStack.push875 (new StackEntry(nodeStack.peek().treeNode.children.get(index), index));876 retVal = nodeStack.peek().treeNode.guiElement;877 }878 879 return retVal;880 }881 882 /**883 * <p>884 * navigates the traverser to the given node in the GUI model885 * </p>886 */887 private boolean navigateTo(TreeNode node) {888 if (hasFirstChild()) {889 IGUIElement childElement = firstChild();890 891 while (childElement != null) {892 if (childElement.equals(node.guiElement)) {893 return true;894 }895 else if (navigateTo(node)) {896 return true;897 }898 else {899 childElement = nextSibling();900 }901 }902 903 parent();904 }905 906 return false;907 }908 909 /**910 * <p>911 * internal class needed to fill the stack with nodes of the GUI models and their912 * respective index in the children of the parent node.913 * </p>914 */915 private class StackEntry {916 917 /** */918 private TreeNode treeNode;919 920 /** */921 private int index;922 923 /**924 * <p>925 * creates a new stack entry.926 * </p>927 */928 private StackEntry(TreeNode treeNode, int index) {929 this.treeNode = treeNode;930 this.index = index;931 }932 }933 }934 935 /**936 * <p>937 * Used internally for building up the tree of GUI elements.938 * </p>939 *940 * @version 1.0941 * @author Patrick Harms, Steffen Herbold942 */943 private static class TreeNode implements Serializable {944 945 /** */946 private static final long serialVersionUID = 1L;947 948 /**949 * <p>950 * GUI element associated with the TreeNode.951 * </p>952 */953 private IGUIElement guiElement;954 955 /**956 * <p>957 * Children of the TreeNode.958 * </p>959 */960 private List<TreeNode> children;961 962 /**963 * <p>964 * Adds a child to the current node while keeping all lists of nodes up to date965 * </p>966 *967 * @param guiElement968 * GUI element that will be associated with the new child969 * @return the added child970 */971 private TreeNode addChild(IGUIElement guiElement) {972 if (children == null) {973 children = new ArrayList<TreeNode>();974 }975 976 TreeNode child = new TreeNode();977 child.guiElement = guiElement;978 children.add(child);979 980 return child;981 }982 983 /**984 *985 * <p>986 * Adds a TreeNode as child to the current node. This way, the whole sub-tree is added.987 * </p>988 *989 * @param node990 * child node that is added991 * @return node that has been added992 */993 private TreeNode addChildNode(TreeNode node) {994 if (children == null) {995 children = new ArrayList<TreeNode>();996 }997 children.add(node);998 return node;999 }1000 1001 /*1002 * (non-Javadoc)1003 *1004 * @see java.lang.Object#toString()1005 */1006 @Override1007 public String toString() {1008 return guiElement.toString();1009 }1010 1011 }1012 60 } -
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/IGUIElement.java
r1876 r2146 15 15 package de.ugoe.cs.autoquest.eventcore.guimodel; 16 16 17 import de.ugoe.cs.autoquest.eventcore.I EventTarget;17 import de.ugoe.cs.autoquest.eventcore.IHierarchicalEventTarget; 18 18 19 19 /** … … 25 25 * @author Patrick Harms 26 26 */ 27 public interface IGUIElement extends I EventTarget {28 27 public interface IGUIElement extends IHierarchicalEventTarget { 28 29 29 /** 30 30 * <p> … … 99 99 /** 100 100 * <p> 101 * Updates the specification of a GUI element with another specification, e.g., to add further102 * known names of the GUI element.103 * </p>104 *105 * @param furtherSpec106 * additional specification107 */108 public void updateSpecification(IGUIElementSpec furtherSpec);109 110 /**111 * <p>112 * The {@link IGUIElement} that is passed by this function is equal to the current GUI element113 * and will hereafter be treated as such.114 * </p>115 *116 * @param guiElement117 * GUI element that is equal118 */119 public void addEqualGUIElement(IGUIElement equalElement);120 121 /**122 * <p>123 101 * Returns a measure for the distance of this {@link IGUIElement} to the provided one. Distance 124 102 * means a measure for the distance in display of the rendered GUI. The returned values must be -
trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/IGUIElementSpec.java
r990 r2146 17 17 import java.io.Serializable; 18 18 19 import de.ugoe.cs.autoquest.eventcore.IEventTargetSpec; 20 19 21 /** 20 22 * <p> … … 25 27 * @author Patrick Harms, Steffen Herbold 26 28 */ 27 public interface IGUIElementSpec extends Serializable {29 public interface IGUIElementSpec extends Serializable, IEventTargetSpec { 28 30 29 31 /** … … 51 53 public String[] getTypeHierarchy(); 52 54 53 /**54 * <p>55 * Evaluates if two GUI specifications are similar. Similar means that a heuristic determines56 * that the two GUI specifications describe the same GUI element.57 * </p>58 *59 * @param other60 * specification whose similarity to this is evaluated61 * @return true if the specifications are similar; false otherwise62 */63 public boolean getSimilarity(IGUIElementSpec other);64 65 /**66 * <p>67 * Defines that {@link IGUIElement} implementations have to define equals.68 * </p>69 *70 * @see Object#equals(Object)71 */72 @Override73 public boolean equals(Object other);74 75 /**76 * <p>77 * Defines that {@link IGUIElement} implementations have to define hashCode.78 * </p>79 *80 * @see Object#hashCode()81 */82 @Override83 public int hashCode();84 55 }
Note: See TracChangeset
for help on using the changeset viewer.