package org.sikuli.slides.driver;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.List;
import org.sikuli.slides.api.io.PPTXSlidesReader;
import org.sikuli.slides.api.io.SlidesReader;
import org.sikuli.slides.api.models.Slide;
import org.sikuli.slides.driver.annotations.WidgetSlide;
public class WidgetSlideFactory {
/**
* Create an object where each field represents an {@link Widget} that can be found and interacted with
* automatically
*
* @param classToProxy
* @return
*/
public static <T> T create(Class<T> classToProxy) {
if (!classToProxy.isAnnotationPresent(WidgetSlide.class))
// path to pptx file is not specified
throw new RuntimeException("@Source annotation is missing in " + classToProxy + ". Need this to know where" +
"to read slides");
WidgetSlide source = classToProxy.getAnnotation(WidgetSlide.class);
source.value();
// if (source.url().isEmpty() > 0){
SlidesReader reader = new PPTXSlidesReader();
List<Slide> slides;
// File file = new File(source.value());
try {
if (!source.value().isEmpty()){
slides = reader.read(new File(source.value()));
}else if (!source.url().isEmpty()){
slides = reader.read(new URL(source.url()));
}else{
throw new RuntimeException("@Source is not specified correctly");
}
} catch (IOException e) {
// error in reading the slides from the given source
throw new RuntimeException(e);
}
DefaultSlideDriver driver;
if (slides.size() == 0){
// there is no slide found
driver = new DefaultSlideDriver();
}else{
driver = new DefaultSlideDriver(slides.get(0));
}
T page = instantiatePage(driver, classToProxy);
initElements(driver, page);
return page;
}
static void initElements(SlideDriver driverRef, Object page) {
initElements(new DefaultWidgetLocatorFactory(driverRef), page);
}
//
static void initElements(WidgetLocatorFactory factoryRef, Object page) {
initElements(new DefaultFieldDecorator(factoryRef), page);
}
static void initElements(FieldDecorator decorator, Object page) {
Class<?> proxyIn = page.getClass();
while (proxyIn != Object.class) {
proxyFields(decorator, page, proxyIn);
proxyIn = proxyIn.getSuperclass();
}
}
private static void proxyFields(FieldDecorator decorator, Object page, Class<?> proxyIn) {
Field[] fields = proxyIn.getDeclaredFields();
for (Field field : fields) {
Object value = decorator.decorate(page.getClass().getClassLoader(), field);
if (value != null) {
try {
field.setAccessible(true);
field.set(page, value);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
private static <T> T instantiatePage(SlideDriver driver, Class<T> pageClassToProxy) {
try {
try {
// try to see if there's a constructor that takes a Driver object as an argument
Constructor<T> constructor = pageClassToProxy.getConstructor(SlideDriver.class);
return constructor.newInstance(driver);
} catch (NoSuchMethodException e) {
// if not, use the default constructor
return pageClassToProxy.newInstance();
}
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}