/
ComponentsManager.java
129 lines (112 loc) · 4.09 KB
/
ComponentsManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package org.fluentlenium.core.components;
import com.sun.jna.WeakIdentityHashMap;
import org.fluentlenium.core.proxy.ProxyElementListener;
import org.fluentlenium.core.proxy.LocatorProxies;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.internal.WrapsElement;
import org.openqa.selenium.support.pagefactory.ElementLocator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Manage living components for a WebDriver instance.
* <p>
* A component is an Object implementing no particular interface, but capable a wrapping
* a {@link org.openqa.selenium.WebElement}.
* <p>
* {@link org.fluentlenium.core.domain.FluentWebElement} is the most common component.
*/
public class ComponentsManager implements ComponentInstantiator, ComponentAccessor, ProxyElementListener {
private final WebDriver driver;
private final ComponentInstantiator instantiator;
//TODO: IdentityHashMap or WeakIdentityHashMap ?
private Map<WebElement, Object> components = new WeakIdentityHashMap();
public ComponentsManager(WebDriver driver) {
this.driver = driver;
this.instantiator = new DefaultComponentInstantiator(this.driver, this);
}
public ComponentsManager(WebDriver driver, ComponentInstantiator instantiator) {
this.driver = driver;
this.instantiator = instantiator;
}
public ComponentInstantiator getInstantiator() {
return instantiator;
}
/**
* Get the related component from the given element.
*
* @param element
* @return
*/
public Object getComponent(WebElement element) {
return components.get(unwrapElement(element));
}
/**
* Get all the component related to this webDriver.
*
* @return
*/
public Collection<ComponentBean> getAllComponents() {
List<ComponentBean> allComponents = new ArrayList<>();
for (Map.Entry<WebElement, Object> entry : components.entrySet()) {
allComponents.add(new ComponentBean(entry.getValue(), entry.getKey()));
}
return allComponents;
}
@Override
public boolean isComponentClass(Class<?> componentClass) {
return instantiator.isComponentClass(componentClass);
}
@Override
public <T> T newComponent(Class<T> componentClass, WebElement element) {
T component;
try {
component = instantiator.newComponent(componentClass, element);
} catch (Exception e) {
throw new ComponentException(componentClass.getName()
+ " is not a valid component class. No valid constructor found (WebElement) or (WebElement, WebDriver)", e);
}
WebElement webElement = unwrapElement(element);
LocatorProxies.addProxyListener(webElement, this);
components.put(webElement, component);
return component;
}
@Override
public void proxyElementSearch(Object proxy, ElementLocator locator) {
}
/**
* When the underlying element of a WebElement Proxy is found, we have to update the components map.
*
*
* @param proxy proxy element.
* @param locator
* @param element found element.
*/
@Override
public synchronized void proxyElementFound(Object proxy, ElementLocator locator, WebElement element) {
Object component = components.remove(proxy);
if (component != null) {
components.put(unwrapElement(element), component);
}
}
private WebElement unwrapElement(WebElement element) {
if (element instanceof WrapsElement) {
WebElement wrappedElement = ((WrapsElement) element).getWrappedElement();
if (wrappedElement != element && wrappedElement != null) {
return unwrapElement(wrappedElement);
}
}
return element;
}
/**
* Release this manager.
*/
public void release() {
for (WebElement element : components.keySet()) {
LocatorProxies.removeProxyListener(element, this);
}
components.clear();
}
}