
org.bidib.wizard.script.engine.ScriptEngine Maven / Gradle / Ivy
package org.bidib.wizard.script.engine;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.bidib.wizard.script.ScriptCommand;
import org.bidib.wizard.script.ScriptEngineListener;
import org.bidib.wizard.script.Scripting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ScriptEngine {
private static final Logger LOGGER = LoggerFactory.getLogger(ScriptEngine.class);
private final Object scriptWorkerLock = new Object();
private Thread scriptWorker;
private AtomicBoolean scriptRunning = new AtomicBoolean(false);
private AtomicBoolean scriptRepeating = new AtomicBoolean(false);
private List> scriptCommands;
private T scripting;
private final Map context;
private List> engineListeners = new LinkedList>();
public enum ScriptStatus {
STOPPED, RUNNING, FINISHED
}
public ScriptEngine(T scripting, final Map context) {
this.scripting = scripting;
this.context = context;
}
public void addScriptEngineListener(ScriptEngineListener listener) {
engineListeners.add(listener);
}
public void removeScriptEngineListener(ScriptEngineListener listener) {
engineListeners.remove(listener);
}
public void setScriptRepeating(boolean repeating) {
this.scriptRepeating.set(repeating);
}
public void setScriptCommands(List> scriptCommands) {
LOGGER.info("Set the new script commands.");
synchronized (scriptWorkerLock) {
if (scriptRunning.get()) {
LOGGER
.warn("The script engine is currently processing commands. Stop the engine before setting new commands.");
throw new IllegalStateException(
"The script engine is currently processing commands. Stop the engine before setting new commands.");
}
this.scriptCommands = scriptCommands;
}
}
public void startScript() {
synchronized (scriptWorkerLock) {
if (scriptCommands != null && scriptWorker == null) {
LOGGER.info("Create and start scriptWorker.");
scriptRunning.set(true);
signalScriptStatus(ScriptStatus.RUNNING);
scriptWorker = new Thread(new Runnable() {
@Override
public void run() {
LOGGER.info("Start execution of script commands.");
try {
do {
for (ScriptCommand command : scriptCommands) {
if (!scriptRunning.get()) {
LOGGER.info("Script execution is stopped.");
break;
}
updateCurrentCommand(command);
command.execute(scripting, context);
}
}
while (scriptRepeating.get() && scriptRunning.get());
}
catch (Exception ex) {
LOGGER.warn("Executing script command has failed.", ex);
}
LOGGER.info("Script worker has finished.");
synchronized (scriptWorkerLock) {
LOGGER.info("Release scriptWorker.");
scriptWorker = null;
}
// the script has finished
scriptRunning.set(false);
signalScriptStatus(ScriptStatus.FINISHED);
}
});
scriptWorker.start();
LOGGER.info("Start script worker has passed.");
}
else if (scriptWorker != null) {
LOGGER.warn("Script worker is still running.");
}
}
}
public void stopScript() {
scriptRunning.set(false);
LOGGER.info("Stop the script.");
synchronized (scriptWorkerLock) {
if (scriptWorker != null) {
LOGGER.info("Interrupt the script worker.");
scriptWorker.interrupt();
}
else {
LOGGER.info("Script worker is not available.");
}
}
}
private void signalScriptStatus(ScriptStatus scriptStatus) {
for (ScriptEngineListener listener : engineListeners) {
listener.scriptStatusChanged(scriptStatus);
}
}
private void updateCurrentCommand(final ScriptCommand command) {
for (ScriptEngineListener listener : engineListeners) {
listener.currentCommandChanged(command);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy