package net.thucydides.core.annotations.locators; import net.thucydides.core.annotations.ImplementedBy; import net.thucydides.core.annotations.NotImplementedException; import net.thucydides.core.pages.WebElementFacade; import org.openqa.selenium.WebDriver; import org.openqa.selenium.support.pagefactory.ElementLocator; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class SmartElementHandler implements InvocationHandler{ private final ElementLocator locator; private final WebDriver driver; private final Class<?> implementerClass; private final long timeoutInMilliseconds; private Class<?> getImplementer(Class<?> interfaceType) { if (!interfaceType.isInterface()){ throw new NotImplementedException(interfaceType.getSimpleName() + " is not an interface"); } ImplementedBy implBy = interfaceType.getAnnotation(ImplementedBy.class); if (implBy == null){ throw new NotImplementedException(interfaceType.getSimpleName() + " is not implemented by any class (or not annotated by @ImplementedBy)"); } Class<?> implementerClass = implBy.value(); if (!interfaceType.isAssignableFrom(implementerClass)) { throw new NotImplementedException("implementer Class does not implement the interface " + interfaceType.getName()); } return implementerClass; } public SmartElementHandler(Class<?> interfaceType, ElementLocator locator, WebDriver driver, long timeoutInMilliseconds) { this.driver = driver; this.locator = locator; if (!WebElementFacade.class.isAssignableFrom(interfaceType)) { throw new NotImplementedException("interface not assignable to WebElementFacade"); } this.implementerClass = getImplementer(interfaceType); this.timeoutInMilliseconds = timeoutInMilliseconds; } public Object invoke(Object object, Method method, Object[] objects) throws Throwable { try { if ("getWrappedElement".equals(method.getName())) { return locator.findElement(); } Constructor<?> constructor = implementerClass.getConstructor(WebDriver.class, ElementLocator.class, long.class); Object webElementFacadeExt = constructor.newInstance(driver, locator, timeoutInMilliseconds); return method.invoke(implementerClass.cast(webElementFacadeExt), objects); } catch (InvocationTargetException e) { // Unwrap the underlying exception throw e.getCause(); } } }