1   package com.atlassian.pageobjects.elements;
2   
3   import com.atlassian.pageobjects.PageBinder;
4   import com.atlassian.pageobjects.binder.PostInjectionProcessor;
5   import com.atlassian.pageobjects.util.InjectUtils;
6   import org.openqa.selenium.By;
7   
8   import javax.inject.Inject;
9   import java.lang.reflect.Field;
10  
11  import static com.atlassian.pageobjects.util.InjectUtils.forEachFieldWithAnnotation;
12  import static com.google.common.base.Preconditions.checkArgument;
13  
14  /**
15   * Find fields marked with @ElementBy annotation and set them to instances of WebDriverElement
16   */
17  public class ElementByPostInjectionProcessor implements PostInjectionProcessor
18  {
19      @Inject
20      PageBinder pageBinder;
21  
22      public <T> T process(T pageObject)
23      {
24          injectElements(pageObject);
25          return pageObject;
26      }
27  
28      private void injectElements(final Object instance)
29      {
30          forEachFieldWithAnnotation(instance, ElementBy.class, new InjectUtils.FieldVisitor<ElementBy>()
31          {
32              public void visit(Field field, ElementBy annotation)
33              {
34                  PageElement element = createElement(field, annotation);
35                  try
36                  {
37                      field.setAccessible(true);
38                      field.set(instance, element);
39                  }
40                  catch (IllegalAccessException e)
41                  {
42                      throw new RuntimeException(e);
43                  }
44              }
45          });
46      }
47  
48      private PageElement createElement(Field field, ElementBy elementBy)
49      {
50          By by;
51  
52          if (elementBy.className().length() > 0)
53          {
54              by = By.className(elementBy.className());
55          }
56          else if (elementBy.id().length() > 0)
57          {
58              by = By.id(elementBy.id());
59          }
60          else if (elementBy.linkText().length() > 0)
61          {
62              by = By.linkText(elementBy.linkText());
63          }
64          else if (elementBy.partialLinkText().length() > 0)
65          {
66              by = By.partialLinkText(elementBy.partialLinkText());
67          }
68          else if(elementBy.cssSelector().length() >0)
69          {
70              by = By.cssSelector(elementBy.cssSelector());
71          }
72          else if(elementBy.name().length() > 0)
73          {
74              by = By.name(elementBy.name());
75          }
76          else if(elementBy.xpath().length() > 0)
77          {
78              by = By.xpath(elementBy.xpath());
79          }
80          else if(elementBy.tagName().length() > 0)
81          {
82              by = By.tagName(elementBy.tagName());
83          }
84          else
85          {
86              throw new IllegalArgumentException("No selector found");
87          }
88          Class<? extends PageElement> fieldType = getFieldType(field);
89          return pageBinder.bind(WebDriverElementMappings.findMapping(fieldType), by, elementBy.timeoutType());
90      }
91  
92      @SuppressWarnings({"unchecked"})
93      private Class<? extends PageElement> getFieldType(Field field) {
94          Class<?> realType = field.getType();
95          checkArgument(PageElement.class.isAssignableFrom(realType), "Field type " + realType.getName()
96                  + " does not implement " + PageElement.class.getName());
97          return (Class<? extends PageElement>) realType;
98      }
99  }