View Javadoc

1   package com.atlassian.pageobjects.elements.query.webdriver;
2   
3   import com.atlassian.annotations.Internal;
4   import com.atlassian.pageobjects.elements.WebDriverLocatable;
5   import com.google.common.base.Function;
6   import com.google.common.base.Supplier;
7   import org.openqa.selenium.NoSuchElementException;
8   import org.openqa.selenium.StaleElementReferenceException;
9   import org.openqa.selenium.WebDriver;
10  import org.openqa.selenium.WebElement;
11  
12  import javax.annotation.Nonnull;
13  
14  import static com.atlassian.pageobjects.elements.WebDriverLocatable.LocateTimeout.zero;
15  import static com.atlassian.pageobjects.elements.util.StringConcat.asString;
16  import static com.google.common.base.Preconditions.checkNotNull;
17  
18  /**
19   * <p/>
20   * {@link WebDriverLocatable} based timed query that retrieves {@link WebElement} using provided
21   * {@link WebDriverLocatable} and applies provided function from that element to the target value.
22   *
23   * <p/>
24   * If given element is not found, the 'invalid value' semantics of the timed query are applied. 
25   *
26   */
27  @Internal
28  public class WebDriverLocatableBasedTimedQuery<T> extends GenericWebDriverTimedQuery<T>
29  {
30      private final WebDriverLocatable locatable;
31  
32      public WebDriverLocatableBasedTimedQuery(WebDriverLocatable locatable, WebDriver driver,
33                                               Function<WebElement, T> valueProvider, long timeout)
34      {
35          super(new LocatableBasedSupplier<T>(driver, locatable, valueProvider), timeout);
36          this.locatable = locatable;
37      }
38  
39      public WebDriverLocatableBasedTimedQuery(WebDriverLocatable locatable, WebDriver driver,
40                                               Function<WebElement, T> valueProvider, long timeout, long interval)
41      {
42          super(new LocatableBasedSupplier<T>(driver, locatable, valueProvider),
43                  timeout, interval);
44          this.locatable = locatable;
45      }
46  
47      public WebDriverLocatableBasedTimedQuery(WebDriverLocatable locatable, WebDriver driver,
48                                               Function<WebElement, T> valueProvider, long timeout, long interval,
49                                               T invalidValue)
50      {
51          super(new LocatableBasedSupplier<T>(driver, locatable, valueProvider, invalidValue),
52                  timeout, interval);
53          this.locatable = locatable;
54      }
55  
56      public WebDriverLocatableBasedTimedQuery(WebDriverLocatableBasedTimedQuery<T> origin, long timeout)
57      {
58          super(origin.webElementSupplier(), timeout, origin.interval);
59          this.locatable = origin.locatable;
60      }
61  
62      LocatableBasedSupplier<T> webElementSupplier()
63      {
64          return (LocatableBasedSupplier<T>) valueSupplier;
65      }
66  
67      Function<WebElement,T> valueProvider()
68      {
69          return webElementSupplier().valueProvider;
70      }
71  
72      @Override
73      @Nonnull
74      public String toString()
75      {
76          return asString(super.toString(), "[locatable=", locatable, ",valueProvider=", valueProvider(), "]");
77      }
78  
79      private static class LocatableBasedSupplier<S> implements Supplier<S>
80      {
81          private final WebDriver webDriver;
82          private final WebDriverLocatable locatable;
83          private final Function<WebElement, S> valueProvider;
84          private final S invalidValue;
85  
86           public LocatableBasedSupplier(WebDriver webDriver, WebDriverLocatable locatable,
87                                         Function<WebElement, S> valueProvider, S invalid)
88          {
89              this.valueProvider = valueProvider;
90              this.webDriver = webDriver;
91              this.locatable = checkNotNull(locatable);
92              this.invalidValue = invalid;
93          }
94  
95          public LocatableBasedSupplier(WebDriver webDriver, WebDriverLocatable locatable,
96                                        Function<WebElement, S> valueProvider)
97          {
98              this(webDriver, locatable, valueProvider, null);
99          }
100 
101         public S get()
102         {
103             try
104             {
105                 return valueProvider.apply((WebElement) locatable.waitUntilLocated(webDriver, zero()));
106             }
107             catch(StaleElementReferenceException e)
108             {
109                 // element became stale between the time we got it from the locatable and we called the
110                 // value provider. Error out here and try on next poll.
111                 throw new InvalidValue(invalidValue);
112             }
113             catch (NoSuchElementException e1)
114             {
115                 throw new InvalidValue(invalidValue);
116             }
117         }
118     }
119 }