All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.wizard.script.engine.ScriptEngine Maven / Gradle / Ivy

There is a newer version: 2.0.0-M1
Show newest version
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