package jp.vmi.selenium.selenese.utils;
import java.util.Iterator;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.NotFoundException;
import org.openqa.selenium.StaleElementReferenceException;
/**
* Utilities for Selenium.
*/
public class SeleniumUtils {
private SeleniumUtils() {
}
/**
* string-matching pattern of SeleniumIDE.
*/
public static class SeleniumPattern {
@SuppressWarnings("javadoc")
public static enum Type {
REGEXP, REGEXPI, GLOB, EXACT
}
/**
* Type of string-matching pattern.
*/
public final Type type;
/**
* Regular Expression of pattern.
*/
public final Pattern regexpPattern;
/**
* String of pattern.
*/
public final String stringPattern;
/**
* Constructor.
*
* @param pattern string-matching pattern.
*/
public SeleniumPattern(String pattern) {
String[] p = pattern.split(":", 2);
if (p.length == 2) {
String type = p[0].toLowerCase();
if ("regexp".equals(type)) {
this.type = Type.REGEXP;
this.regexpPattern = Pattern.compile(p[1]);
this.stringPattern = p[1];
return;
} else if ("regexpi".equals(type)) {
this.type = Type.REGEXPI;
this.regexpPattern = Pattern.compile(p[1], Pattern.CASE_INSENSITIVE);
this.stringPattern = p[1];
return;
} else if ("glob".equals(type)) {
pattern = p[1];
// don't return here.
} else if ("exact".equals(type)) {
this.type = Type.EXACT;
this.regexpPattern = null;
this.stringPattern = p[1];
return;
}
}
if (pattern.indexOf('*') >= 0 || pattern.indexOf('?') >= 0) {
this.type = Type.GLOB;
// see http://stackoverflow.com/a/3619098
StringBuilder re = new StringBuilder("\\A\\Q");
re.append(pattern.replace("*", "\\E.*\\Q").replace("?", "\\E.\\Q"));
if (re.length() >= 6 && re.charAt(4) == '\\' && re.charAt(5) == 'E')
re.delete(2, 6);
int len = re.length();
if (re.charAt(len - 2) == '\\' && re.charAt(len - 1) == 'Q')
re.setCharAt(re.length() - 1, 'z');
else
re.append("\\E\\z");
this.regexpPattern = Pattern.compile(re.toString(), Pattern.DOTALL);
} else {
this.type = Type.EXACT;
this.regexpPattern = null;
}
this.stringPattern = pattern;
}
/**
* Match pattern.
*
* @param input input string.
* @return true if matched.
*/
public boolean matches(String input) {
input = normalizeSpaces(input);
switch (type) {
case REGEXP:
case REGEXPI:
case GLOB:
return regexpPattern.matcher(input).find();
case EXACT:
return normalizeSpaces(stringPattern).equals(input);
default:
throw new UnsupportedOperationException(type.toString());
}
}
@Override
public String toString() {
return "SeleniumPattern[" + type + ":" + StringEscapeUtils.escapeJava(stringPattern) + "]";
}
}
/**
* String-match pattern.
*
* @param pattern pattern. prefix is "glob:", "regexp:", "regexpi:", or "exact:".
* @param input input string.
* @return true if matched pattern.
*/
public static boolean patternMatches(String pattern, CharSequence input) {
return new SeleniumPattern(pattern).matches(input.toString());
}
/**
* Unifty U+0020 and U+00A0, Trim, and compress spaces in string.
*
* @param str string.
* @return normalized string.
*/
public static String normalizeSpaces(String str) {
int si = str.indexOf(' ');
int ni = str.indexOf('\u00A0');
if (si < 0 && ni < 0)
return str;
int len = str.length();
StringBuilder buf = new StringBuilder(len);
boolean skipSpc = true;
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
if (c != ' ' && c != '\u00A0') {
buf.append(c);
skipSpc = false;
} else if (!skipSpc) {
buf.append(' ');
skipSpc = true;
}
// skip if skipSpc && (c == ' ' || c == '\u00A0)
}
int blen = buf.length();
if (blen > 0 && buf.charAt(blen - 1) == ' ')
buf.deleteCharAt(blen - 1);
return buf.toString();
}
/**
* Convert to String from the result of execute().
*
* @param <T> the type of result object.
* @param result the result of execute().
* @return converted string.
*/
public static <T> String convertToString(T result) {
if (result == null)
return "";
else if (result instanceof Object[])
return StringUtils.join((Object[]) result, ',');
else if (result instanceof Iterable)
return StringUtils.join((Iterable<?>) result, ',');
else if (result instanceof Iterator)
return StringUtils.join((Iterator<?>) result, ',');
else
return result.toString();
}
/**
* Check if Exception type is "element not found".
*
* @param e RuntimeException
* @return true if the exception is "element not found".
*/
public static boolean isElementNotFound(RuntimeException e) {
return e instanceof NotFoundException
|| e instanceof StaleElementReferenceException
|| e.getCause() instanceof NotFoundException
|| e.getCause() instanceof StaleElementReferenceException;
}
}