package com.github.vbauer.jconditions.checker;
import com.github.vbauer.jconditions.annotation.IfScript;
import com.github.vbauer.jconditions.core.CheckerContext;
import com.github.vbauer.jconditions.core.ConditionChecker;
import com.github.vbauer.jconditions.util.PropUtils;
import com.github.vbauer.jconditions.util.ReflexUtils;
import com.github.vbauer.jconditions.util.ScriptUtils;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.SimpleScriptContext;
import java.util.concurrent.Callable;
/**
* @author Vladislav Bauer
*/
public class IfScriptChecker implements ConditionChecker<IfScript> {
public static final String CONTEXT_ENV = "env";
public static final String CONTEXT_PROPS = "props";
public static final String CONTEXT_TEST = "test";
public static final String CONTEXT_CONSOLE = "console";
public static final String CONTEXT_CONTEXT = "context";
/**
* {@inheritDoc}
*/
@Override
public boolean isSatisfied(final CheckerContext<IfScript> context) throws Exception {
final Object testInstance = context.getInstance();
final IfScript annotation = context.getAnnotation();
@SuppressWarnings("rawtypes")
final Class<? extends Callable> contextProviderClass = annotation.context();
final String engineName = annotation.engine();
final String[] scripts = annotation.value();
final ScriptEngine scriptEngine = ScriptUtils.findScriptEngine(engineName);
if (scriptEngine != null) {
final Object extraContext = getExtraContext(testInstance, contextProviderClass);
final ScriptContext scriptContext = createScriptContext(testInstance, extraContext);
return isSatisfied(scriptEngine, scriptContext, scripts);
}
return false;
}
private boolean isSatisfied(
final ScriptEngine scriptEngine, final ScriptContext scriptContext, final String... scripts
) throws Exception {
for (final String script : scripts) {
final Object eval = scriptEngine.eval(script, scriptContext);
if (!isTrueValue(eval)) {
return false;
}
}
return scripts.length > 0;
}
private boolean isTrueValue(final Object value) {
if (value instanceof Number) {
return ((Number) value).doubleValue() > 0;
}
return Boolean.valueOf(String.valueOf(value));
}
private ScriptContext createScriptContext(
final Object testInstance, final Object extraContext
) {
final ScriptContext context = new SimpleScriptContext();
ScriptUtils.addAttribute(context, CONTEXT_CONTEXT, extraContext);
ScriptUtils.addAttribute(context, CONTEXT_TEST, testInstance);
ScriptUtils.addAttribute(context, CONTEXT_CONSOLE, System.console());
ScriptUtils.addAttribute(context, CONTEXT_ENV, System.getenv());
ScriptUtils.addAttribute(
context, CONTEXT_PROPS,
PropUtils.convertPropertiesToMap(System.getProperties())
);
return context;
}
@SuppressWarnings("rawtypes")
private Object getExtraContext(
final Object testInstance, final Class<? extends Callable> providerClass
) throws Exception {
if (providerClass != null && providerClass != Callable.class) {
final Callable<?> provider = ReflexUtils.instantiate(testInstance, providerClass);
return provider.call();
}
return null;
}
}