package jp.vmi.selenium.selenese.javascript;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
/**
* Javascript Function.
*/
public class JSFunction {
private final String function;
private JSFunction(String function) {
this.function = function;
}
private static final Pattern BEGIN_RE = Pattern.compile("function\\s+(?<name>\\w+)\\((?<args>.*?)\\).*");
private static final Pattern END_RE = Pattern.compile("\\}.*");
/**
* Load Javascript file.
*
* @param is InputStream object.
* @return JSFunction
*/
public static Map<String, JSFunction> load(InputStream is) {
Map<String, JSFunction> functions = new HashMap<>();
String line;
String name = null;
boolean hasArgs = false;
StringBuilder body = null;
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
while ((line = br.readLine()) != null) {
if (name == null) {
Matcher matcher = BEGIN_RE.matcher(line);
if (matcher.matches()) {
name = matcher.group("name");
String args = matcher.group("args");
if (hasArgs = !args.isEmpty())
body = new StringBuilder("return (function(" + args + "){");
else
body = new StringBuilder();
}
} else {
if (END_RE.matcher(line).matches()) {
if (hasArgs)
body.append("}).apply(null, arguments)");
functions.put(name, new JSFunction(body.toString()));
name = null;
body = null;
hasArgs = false;
} else {
body.append(line.trim()).append('\n');
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return functions;
}
/**
* Load Javascript file as a function.
*
* @param is InputStream object.
* @return JSFunction
*/
public static JSFunction loadFunction(InputStream is) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
String body = br.lines().collect(Collectors.joining("\n", "return (", ").apply(null, arguments);"));
return new JSFunction(body);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Call Javascript function.
*
* @param driver WebDriver object.
* @param args arguments.
* @param <T> type of function result.
* @return function result.
*/
public <T> T call(WebDriver driver, Object... args) {
@SuppressWarnings("unchecked")
T result = (T) ((JavascriptExecutor) driver).executeScript(function, args);
return result;
}
}