package jp.vmi.selenium.selenese.locator;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import jp.vmi.selenium.selenese.utils.SeleniumUtils.SeleniumPattern;
import jp.vmi.selenium.selenese.utils.XPathUtils;
class LinkHandler implements LocatorHandler {
@Override
public String locatorType() {
return "link";
}
private List<WebElement> findByRegexp(WebDriver driver, By by, Pattern pattern) {
List<WebElement> result = new ArrayList<>();
List<WebElement> as = driver.findElements(by);
for (WebElement a : as) {
String text;
try {
if ((text = a.getText()) == null)
text = "";
} catch (StaleElementReferenceException e) {
continue;
}
Matcher matcher = pattern.matcher(text);
if (matcher.find())
result.add(a);
}
return result;
}
private List<WebElement> findByGlobString(WebDriver driver, SeleniumPattern sp) {
boolean and = false;
StringBuilder xpath = new StringBuilder("//a[");
for (String ss : sp.stringPattern.split("[*?]+")) {
if (StringUtils.isEmpty(ss))
continue;
if (and)
xpath.append(" and ");
xpath.append("contains(normalize-space(.),");
XPathUtils.appendStringLiteral(xpath, ss);
xpath.append(")");
and = true;
}
xpath.append("]");
By by = and ? By.xpath(xpath.toString()) : By.tagName("a");
return findByRegexp(driver, by, sp.regexpPattern);
}
private List<WebElement> findByExactString(WebDriver driver, SeleniumPattern sp) {
StringBuilder xpath = new StringBuilder("//a[normalize-space(.)=");
XPathUtils.appendStringLiteral(xpath, sp.stringPattern);
xpath.append(']');
return driver.findElements(By.xpath(xpath.toString()));
}
@Override
public List<WebElement> handle(WebDriver driver, String arg) {
SeleniumPattern sp = new SeleniumPattern(arg);
switch (sp.type) {
case REGEXP:
case REGEXPI:
return findByRegexp(driver, By.tagName("a"), sp.regexpPattern);
case GLOB:
return findByGlobString(driver, sp);
case EXACT:
return findByExactString(driver, sp);
default:
throw new UnsupportedOperationException(arg);
}
}
}