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

org.bidib.wizard.mvc.script.controller.NodeScriptController Maven / Gradle / Ivy

There is a newer version: 2.0.0-M1
Show newest version
package org.bidib.wizard.mvc.script.controller;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.bidib.wizard.main.DefaultApplicationContext;
import org.bidib.wizard.mvc.main.controller.MainControllerInterface;
import org.bidib.wizard.mvc.main.model.AccessoryLabels;
import org.bidib.wizard.mvc.main.model.AnalogPortLabels;
import org.bidib.wizard.mvc.main.model.BacklightPortLabels;
import org.bidib.wizard.mvc.main.model.ChildLabels;
import org.bidib.wizard.mvc.main.model.InputPortLabels;
import org.bidib.wizard.mvc.main.model.LightPortLabels;
import org.bidib.wizard.mvc.main.model.MacroLabels;
import org.bidib.wizard.mvc.main.model.MainModel;
import org.bidib.wizard.mvc.main.model.MotorPortLabels;
import org.bidib.wizard.mvc.main.model.Node;
import org.bidib.wizard.mvc.main.model.NodeLabels;
import org.bidib.wizard.mvc.main.model.ServoPortLabels;
import org.bidib.wizard.mvc.main.model.SoundPortLabels;
import org.bidib.wizard.mvc.main.model.SwitchPortLabels;
import org.bidib.wizard.mvc.main.model.listener.DefaultNodeListListener;
import org.bidib.wizard.mvc.main.model.listener.NodeListListener;
import org.bidib.wizard.mvc.script.controller.listener.ExecuteScriptListener;
import org.bidib.wizard.mvc.script.model.NodeScriptModel;
import org.bidib.wizard.mvc.script.view.NodeScriptView;
import org.bidib.wizard.mvc.script.view.NodeScripting;
import org.bidib.wizard.mvc.script.view.ScriptParser;
import org.bidib.wizard.script.ScriptCommand;
import org.bidib.wizard.script.ScriptEngineListener;
import org.bidib.wizard.script.engine.ScriptEngine;
import org.bidib.wizard.script.engine.ScriptEngine.ScriptStatus;
import org.bidib.wizard.script.node.NodeScriptCommandList;
import org.bidib.wizard.script.node.NodeScriptCommandList.ExecutionStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vlsolutions.swing.docking.Dockable;
import com.vlsolutions.swing.docking.DockingDesktop;
import com.vlsolutions.swing.docking.DockingUtilities;
import com.vlsolutions.swing.docking.RelativeDockablePosition;
import com.vlsolutions.swing.docking.TabbedDockableContainer;
import com.vlsolutions.swing.docking.event.DockableStateChangeEvent;
import com.vlsolutions.swing.docking.event.DockableStateChangeListener;

public class NodeScriptController implements ExecuteScriptListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(NodeScriptController.class);

    private NodeScriptView nodeScriptView;

    private NodeScriptModel nodeScriptModel;

    private NodeListListener nodeListListener;

    private ScriptEngine scriptEngine;

    private MainModel mainModel;

    public NodeScriptController() {
    }

    public void start(
        final DockingDesktop desktop, final MainModel mainModel, final MainControllerInterface mainController) {
        LOGGER.info("Start the NodeScriptController.");

        // check if the booster table view is already opened
        String searchKey = NodeScriptView.NODE_SCRIPT_VIEW;
        LOGGER.info("Search for view with key: {}", searchKey);
        Dockable view = desktop.getContext().getDockableByKey(searchKey);
        if (view != null) {
            LOGGER.info("Select the existing booster table view.");
            selectWindow(view);
            return;
        }

        LOGGER.info("Create new BoosterTableView.");
        this.mainModel = mainModel;

        nodeScriptModel = new NodeScriptModel();

        nodeScriptModel.addPropertyChangeListener(NodeScriptModel.PROPERTYNAME_NODE_SCRIPT_COMMAND_LIST,
            new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    LOGGER.info("The node script commands have changed.");

                    final NodeScriptCommandList nodeScriptCommandList = nodeScriptModel.getNodeScriptCommandList();

                    if (!ExecutionStatus.pending.equals(nodeScriptCommandList.getExecutionStatus())) {
                        LOGGER.info("The execution status is not pending, skip processing.");
                        return;
                    }

                    List> commands = nodeScriptCommandList.getNodeScriptCommands();
                    if (CollectionUtils.isNotEmpty(commands)) {
                        LOGGER.info("Process the node script commands.");
                        nodeScriptCommandList.setExecutionStatus(ExecutionStatus.pending);

                        Map context = nodeScriptModel.getContext();

                        // create the script engine
                        scriptEngine = new ScriptEngine(mainController.getNodeScripting(), context);
                        scriptEngine.addScriptEngineListener(new ScriptEngineListener() {

                            @Override
                            public void scriptStatusChanged(ScriptStatus scriptStatus) {
                                LOGGER.info("The script status has changed: {}", scriptStatus);

                                switch (scriptStatus) {
                                    case STOPPED:
                                    case FINISHED:
                                        nodeScriptCommandList.setExecutionStatus(ExecutionStatus.finished);
                                        break;
                                    case RUNNING:
                                        nodeScriptCommandList.setExecutionStatus(ExecutionStatus.running);
                                        break;
                                    default:
                                        break;
                                }
                            }

                            @Override
                            public void currentCommandChanged(ScriptCommand command) {
                                LOGGER.info("The current command has changed: {}", command);
                            }
                        });
                        scriptEngine.setScriptCommands(commands);
                        scriptEngine.startScript();
                    }
                    else {
                        nodeScriptCommandList.setExecutionStatus(ExecutionStatus.finished);
                    }

                    LOGGER.info("Reset the commands to execute.");
                }
            });

        nodeScriptView = new NodeScriptView(nodeScriptModel);
        nodeScriptView.setExecuteScriptListener(this);

        if (desktop.getDockables().length > 1) {
            Dockable dock = desktop.getDockables()[1].getDockable();
            // dock.addDockable(boosterTableView, RelativeDockablePosition.RIGHT);

            desktop.createTab(dock, nodeScriptView, 1, true);
            // desktop.split(dock, nodeScriptView, DockingConstants.SPLIT_BOTTOM);
            // desktop.setDockableHeight(nodeScriptView, 0.2d);
        }
        else {
            desktop.addDockable(nodeScriptView, RelativeDockablePosition.RIGHT);
        }

        desktop.addDockableStateChangeListener(new DockableStateChangeListener() {

            @Override
            public void dockableStateChanged(DockableStateChangeEvent event) {
                if (event.getNewState().getDockable().equals(nodeScriptView) && event.getNewState().isClosed()) {
                    LOGGER.info("NodeScriptView was closed, free resources.");

                    if (nodeListListener != null) {
                        LOGGER.info("Remove nodeListListener: {}", nodeListListener);
                        mainModel.removeNodeListListener(nodeListListener);
                        nodeListListener = null;
                    }
                }
            }
        });

        nodeListListener = new DefaultNodeListListener() {

            @Override
            public void nodeChanged() {
                Node selectedNode = mainModel.getSelectedNode();
                LOGGER.info("The selected node has changed: {}", selectedNode);
                nodeScriptModel.setSelectedNode(selectedNode);
            }
        };
        mainModel.addNodeListListener(nodeListListener);

        // initialize
        nodeListListener.nodeChanged();

    }

    private void selectWindow(Dockable dockable) {

        // TODO this should also work with non-tabbed windows
        TabbedDockableContainer container = DockingUtilities.findTabbedDockableContainer(dockable);
        if (container != null) {
            container.setSelectedDockable(dockable);
        }
        else {
            LOGGER.warn("Container not available, select component directly.");
            dockable.getComponent().requestFocusInWindow();
        }
    }

    @Override
    public void executeScript(String script) {

        LOGGER.info("Execute the script on node.");

        NodeLabels nodeLabels =
            (NodeLabels) DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_NODE_LABELS);

        NodeScriptCommandList nodeScriptCommandList = new NodeScriptCommandList();
        List> nodeScriptCommands = new LinkedList<>();
        nodeScriptCommandList.setNodeScriptCommands(nodeScriptCommands);
        nodeScriptCommandList.setExecutionStatus(ExecutionStatus.pending);

        // prepare the context
        HashMap context = new LinkedHashMap<>();
        context.put(ScriptParser.KEY_SELECTED_NODE, nodeScriptModel.getSelectedNode());
        context.put(ScriptParser.KEY_NODE_LABELS, nodeLabels);
        context.put(ScriptParser.KEY_MAIN_MODEL, mainModel);

        long uuid = nodeScriptModel.getSelectedNode().getUniqueId();
        MacroLabels macroLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_MACRO_LABELS, MacroLabels.class);
        context.put(ScriptParser.KEY_MACRO_LABELS, getCopyOfMap(macroLabels, uuid));

        AccessoryLabels accessoryLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_ACCESSORY_LABELS,
                AccessoryLabels.class);
        context.put(ScriptParser.KEY_ACCESSORY_LABELS, getCopyOfMap(accessoryLabels, uuid));

        AnalogPortLabels analogLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_ANALOGPORT_LABELS,
                AnalogPortLabels.class);
        context.put(ScriptParser.KEY_ANALOG_LABELS, getCopyOfMap(analogLabels, uuid));

        BacklightPortLabels backlightLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_BACKLIGHTPORT_LABELS,
                BacklightPortLabels.class);
        context.put(ScriptParser.KEY_BACKLIGHT_LABELS, getCopyOfMap(backlightLabels, uuid));

        InputPortLabels inputLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_INPUTPORT_LABELS,
                InputPortLabels.class);
        context.put(ScriptParser.KEY_INPUT_LABELS, getCopyOfMap(inputLabels, uuid));

        LightPortLabels lightLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_LIGHTPORT_LABELS,
                LightPortLabels.class);
        context.put(ScriptParser.KEY_LIGHT_LABELS, getCopyOfMap(lightLabels, uuid));

        MotorPortLabels motorLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_MOTORPORT_LABELS,
                MotorPortLabels.class);
        context.put(ScriptParser.KEY_MOTOR_LABELS, getCopyOfMap(motorLabels, uuid));

        ServoPortLabels servoLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_SERVOPORT_LABELS,
                ServoPortLabels.class);
        context.put(ScriptParser.KEY_SERVO_LABELS, getCopyOfMap(servoLabels, uuid));

        SoundPortLabels soundLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_SOUNDPORT_LABELS,
                SoundPortLabels.class);
        context.put(ScriptParser.KEY_SOUND_LABELS, getCopyOfMap(soundLabels, uuid));

        SwitchPortLabels switchLabels =
            DefaultApplicationContext.getInstance().get(DefaultApplicationContext.KEY_SWITCHPORT_LABELS,
                SwitchPortLabels.class);
        context.put(ScriptParser.KEY_SWITCH_LABELS, getCopyOfMap(switchLabels, uuid));

        ScriptParser scriptParser = new ScriptParser();
        scriptParser.parseScript(script, nodeScriptCommands, context);

        LOGGER.info("Prepared nodeScriptCommands: {}", nodeScriptCommands);

        // set the nodeScriptCommands in the model
        nodeScriptModel.setNodeScriptCommandList(nodeScriptCommandList, context);
    }

    private Map getCopyOfMap(final ChildLabels inMap, long uuid) {
        Map labelMap = new HashMap();
        if (MapUtils.isNotEmpty(inMap.getLabelMap(uuid))) {
            labelMap.putAll(inMap.getLabelMap(uuid));
        }
        return labelMap;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy