
org.bidib.wizard.mvc.script.controller.NodeScriptController Maven / Gradle / Ivy
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