
org.bidib.wizard.mvc.main.model.Node Maven / Gradle / Ivy
package org.bidib.wizard.mvc.main.model;
import java.awt.Color;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.swing.SwingUtilities;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.bidib.jbidibc.core.enumeration.IdentifyState;
import org.bidib.jbidibc.core.enumeration.SysErrorEnum;
import org.bidib.jbidibc.core.node.ConfigurationVariable;
import org.bidib.jbidibc.core.utils.MessageUtils;
import org.bidib.jbidibc.core.utils.NodeUtils;
import org.bidib.jbidibc.exchange.vendorcv.NodeType;
import org.bidib.jbidibc.exchange.vendorcv.TemplateType;
import org.bidib.jbidibc.exchange.vendorcv.VendorCvData;
import org.bidib.wizard.locale.Resources;
import org.bidib.wizard.mvc.common.view.cvdefinition.CvDefinitionTreeTableModel;
import org.bidib.wizard.mvc.console.controller.ConsoleController;
import org.bidib.wizard.mvc.console.model.ConsoleModel;
import org.bidib.wizard.mvc.main.model.listener.NodeListener;
import org.bidib.wizard.mvc.main.view.cvdef.CvNode;
import org.bidib.wizard.mvc.main.view.cvdef.DeviceNode;
import org.bidib.wizard.mvc.main.view.panel.CvDefinitionTreeHelper;
import org.bidib.wizard.utils.XmlLocaleUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Node implements LabelAware, PropertyChangeListener {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory.getLogger(Node.class);
private final Collection listeners = new LinkedList();
private Boolean addressMessagesEnabled;
private Boolean commandStation = Boolean.FALSE;
private Boolean railComPlusAvailable = Boolean.FALSE;
private Boolean pomUpdateAvailable = Boolean.FALSE;
private Boolean booster = Boolean.FALSE;
private Boolean dccStartEnabled;
private Boolean externalStartEnabled;
private Boolean feedbackMessagesEnabled;
private IdentifyState identifyState;
private SysErrorEnum sysError;
private byte[] reasonData;
private boolean isStall;
private Boolean keyMessagesEnabled;
private String label;
private final org.bidib.jbidibc.core.Node node;
private int storableMacroCount;
private boolean updatable;
private boolean bootloaderNode;
private boolean nodeHasError;
private VendorCvData vendorCV;
private DeviceNode cvRootNode;
private CvDefinitionTreeTableModel treeModel;
private List configVariables;
private Map cvNumberToNodeMap;
private List genericPorts = new LinkedList<>();
private List analogPorts = new LinkedList<>();
private List backlightPorts = new LinkedList<>();
private List inputPorts = new LinkedList<>();
private List lightPorts = new LinkedList<>();
private List motorPorts = new LinkedList<>();
private List servoPorts = new LinkedList<>();
private List soundPorts = new LinkedList<>();
private List switchPorts = new LinkedList<>();
/**
* Create a new node with the associated bidib node.
*
* @param node
* the bidib node is mandatory
* @throws IllegalArgumentException
* if the bidib node is null
*/
public Node(org.bidib.jbidibc.core.Node node) {
if (node == null) {
throw new IllegalArgumentException("The node must not be null!");
}
this.node = node;
}
public long getUniqueId() {
return node.getUniqueId();
}
public void addNodeListener(NodeListener l) {
listeners.add(l);
}
public void removeNodeListener(NodeListener l) {
listeners.remove(l);
}
public Boolean isAddressMessagesEnabled() {
return addressMessagesEnabled;
}
public void setAddressMessagesEnabled(Boolean addressMessagesEnabled) {
this.addressMessagesEnabled = addressMessagesEnabled;
fireAddressMessagesEnabledChanged(addressMessagesEnabled);
}
public Boolean isBooster() {
return booster;
}
public void setBooster(Boolean booster) {
this.booster = booster;
}
public Boolean isCommandStation() {
return commandStation;
}
public void setCommandStation(Boolean commandStation) {
this.commandStation = commandStation;
}
public Boolean isRailComPlusAvailable() {
return railComPlusAvailable;
}
public void setRailComPlusAvailable(Boolean railComPlusAvailable) {
LOGGER.info("Set railComPlusAvailable: {}", railComPlusAvailable);
this.railComPlusAvailable = railComPlusAvailable;
fireRailComPlusAvailableChanged(railComPlusAvailable);
}
public Boolean isPomUpdateAvailable() {
return pomUpdateAvailable;
}
public void setPomUpdateAvailable(Boolean pomUpdateAvailable) {
LOGGER.info("Set pomUpdateAvailable: {}", pomUpdateAvailable);
this.pomUpdateAvailable = pomUpdateAvailable;
firePomUpdateAvailableChanged(pomUpdateAvailable);
}
public Boolean isDccStartEnabled() {
return dccStartEnabled;
}
public void setDccStartEnabled(Boolean dccStartEnabled) {
this.dccStartEnabled = dccStartEnabled;
fireDccStartEnabledChanged(dccStartEnabled);
}
public Boolean isExternalStartEnabled() {
return externalStartEnabled;
}
public void setExternalStartEnabled(Boolean externalStartEnabled) {
this.externalStartEnabled = externalStartEnabled;
fireExternalStartEnabledChanged(externalStartEnabled);
}
public Boolean isFeedbackMessagesEnabled() {
return feedbackMessagesEnabled;
}
public void setFeedbackMessagesEnabled(Boolean feedbackMessagesEnabled) {
this.feedbackMessagesEnabled = feedbackMessagesEnabled;
fireFeedbackMessagesEnabledChanged(feedbackMessagesEnabled);
}
public IdentifyState getIdentifyState() {
return identifyState;
}
public void setIdentifyState(IdentifyState identifyState) {
this.identifyState = identifyState;
fireIdentifyStateChanged(identifyState);
}
public void setErrorState(final SysErrorEnum sysError, final byte[] reasonData) {
this.sysError = sysError;
this.reasonData = reasonData;
fireSysErrorChanged(sysError);
// notify the console
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// ensure console is visible
ConsoleController.ensureConsoleVisible();
try {
String reason = MessageUtils.formatSysError(getNode().getAddr(), sysError, reasonData);
// add line
ConsoleModel.getConsoleModel().addConsoleLine(Color.red,
String.format("The node %s is set to error state: %s", Node.this.toString(), reason));
}
catch (Exception ex) {
LOGGER.warn("Add new error line to console failed, sysError: {}, reasonData: {}", sysError,
reasonData, ex);
}
}
});
}
public SysErrorEnum getErrorState() {
return sysError;
}
public byte[] getReasonData() {
return reasonData;
}
/**
* @return the node has the reset required flag set
*/
public boolean isNodeHasRestartPendingError() {
return SysErrorEnum.BIDIB_ERR_RESET_REQUIRED.equals(sysError);
}
public Boolean isKeyMessagesEnabled() {
return keyMessagesEnabled;
}
public void setKeyMessagesEnabled(Boolean keyMessagesEnabled) {
this.keyMessagesEnabled = keyMessagesEnabled;
fireKeyMessagesEnabledChanged(keyMessagesEnabled);
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
fireLabelChanged(label);
}
public org.bidib.jbidibc.core.Node getNode() {
return node;
}
public int getStorableMacroCount() {
return storableMacroCount;
}
public void setStorableMacroCount(int storableMacroCount) {
this.storableMacroCount = storableMacroCount;
}
/**
* @return the genericPorts
*/
public List getGenericPorts() {
return Collections.unmodifiableList(genericPorts);
}
/**
* @param genericPorts
* the genericPorts to set
*/
public void setGenericPorts(List genericPorts) {
synchronized (this.genericPorts) {
LOGGER.info("Set the generic ports on the node: {}", this);
// remove property change listener
for (GenericPort port : this.genericPorts) {
port.removePropertyChangeListener(this);
}
// set the new generic ports
this.genericPorts.clear();
this.genericPorts.addAll(genericPorts);
// add property change listener
for (GenericPort port : this.genericPorts) {
port.addPropertyChangeListener(this);
}
clearPortCache();
}
}
public void clearPortCache() {
LOGGER.info("Clear the port cache on node: {}", this);
synchronized (genericPorts) {
// clear all cached ports
switchPorts.clear();
servoPorts.clear();
inputPorts.clear();
analogPorts.clear();
lightPorts.clear();
backlightPorts.clear();
motorPorts.clear();
soundPorts.clear();
}
}
public List getAnalogPorts() {
synchronized (genericPorts) {
if (CollectionUtils.isEmpty(analogPorts)) {
LOGGER.debug("Prepare the analog ports.");
for (GenericPort genericPort : genericPorts) {
// fetch the values from the generic port
if (genericPort.isSupportsAnalogPort()) {
LOGGER.trace("The current port supports analog port: {}", genericPort);
AnalogPort analogPort = new AnalogPort(genericPort);
analogPort.setId(genericPort.getPortNumber());
analogPorts.add(analogPort);
}
else {
LOGGER.trace("The current port does not support analog port: {}", genericPort);
}
}
LOGGER.debug("Return the prepared analog ports: {}", analogPorts.size());
}
else {
LOGGER.debug("Return the cached analog ports, size: {}", analogPorts.size());
}
return Collections.unmodifiableList(analogPorts);
}
}
public List getSwitchPorts() {
synchronized (genericPorts) {
if (CollectionUtils.isEmpty(switchPorts)) {
LOGGER.debug("Prepare the switch ports.");
for (GenericPort genericPort : genericPorts) {
// fetch the values from the generic port
if (genericPort.isSupportsSwitchPort()) {
LOGGER.trace("The current port supports switch port: {}", genericPort);
SwitchPort switchPort = new SwitchPort(genericPort);
switchPort.setId(genericPort.getPortNumber());
switchPorts.add(switchPort);
}
else {
LOGGER.trace("The current port does not support switch port: {}", genericPort);
}
}
LOGGER.debug("Return the prepared switch ports: {}", switchPorts.size());
}
else {
LOGGER.debug("Return the cached switch ports, size: {}", switchPorts.size());
}
return Collections.unmodifiableList(switchPorts);
}
}
public List getLightPorts() {
synchronized (genericPorts) {
if (CollectionUtils.isEmpty(lightPorts)) {
LOGGER.debug("Prepare the light ports.");
for (GenericPort genericPort : genericPorts) {
// fetch the values from the generic port
if (genericPort.isSupportsLightPort()) {
LOGGER.trace("The current port supports light port: {}", genericPort);
LightPort lightPort = new LightPort(genericPort);
lightPort.setId(genericPort.getPortNumber());
lightPorts.add(lightPort);
}
else {
LOGGER.trace("The current port does not support light port: {}", genericPort);
}
}
LOGGER.debug("Return the prepared light ports: {}", lightPorts.size());
}
else {
LOGGER.debug("Return the cached light ports, size: {}", lightPorts.size());
}
return Collections.unmodifiableList(lightPorts);
}
}
public List getBacklightPorts() {
synchronized (genericPorts) {
if (CollectionUtils.isEmpty(backlightPorts)) {
LOGGER.debug("Prepare the backlight ports.");
for (GenericPort genericPort : genericPorts) {
// fetch the values from the generic port
if (genericPort.isSupportsBacklightPort()) {
LOGGER.trace("The current port supports backlight port: {}", genericPort);
BacklightPort backlightPort = new BacklightPort(genericPort);
backlightPort.setId(genericPort.getPortNumber());
backlightPorts.add(backlightPort);
}
else {
LOGGER.trace("The current port does not support backlight port: {}", genericPort);
}
}
LOGGER.debug("Return the prepared backlight ports: {}", backlightPorts.size());
}
else {
LOGGER.debug("Return the cached backlight ports, size: {}", backlightPorts.size());
}
return Collections.unmodifiableList(backlightPorts);
}
}
public List getInputPorts() {
synchronized (genericPorts) {
if (CollectionUtils.isEmpty(inputPorts)) {
LOGGER.debug("Prepare the input ports.");
for (GenericPort genericPort : genericPorts) {
// fetch the values from the generic port
if (genericPort.isSupportsInputPort()) {
LOGGER.trace("The current port supports input port: {}", genericPort);
InputPort inputPort = new InputPort(genericPort);
inputPort.setId(genericPort.getPortNumber());
inputPorts.add(inputPort);
}
else {
LOGGER.trace("The current port does not support input port: {}", genericPort);
}
}
}
else {
LOGGER.debug("Return the cached input ports, size: {}", inputPorts.size());
}
return Collections.unmodifiableList(inputPorts);
}
}
public List getServoPorts() {
synchronized (genericPorts) {
if (CollectionUtils.isEmpty(servoPorts)) {
LOGGER.debug("Prepare the servo ports.");
for (GenericPort genericPort : genericPorts) {
// fetch the values from the generic port
if (genericPort.isSupportsServoPort()) {
LOGGER.trace("The current port supports servo port: {}", genericPort);
ServoPort servoPort = new ServoPort(genericPort);
servoPort.setId(genericPort.getPortNumber());
servoPorts.add(servoPort);
}
else {
LOGGER.trace("The current port does not support servo port: {}", genericPort);
}
}
}
else {
LOGGER.debug("Return the cached servo ports.");
}
return Collections.unmodifiableList(servoPorts);
}
}
public List getMotorPorts() {
synchronized (genericPorts) {
if (CollectionUtils.isEmpty(motorPorts)) {
LOGGER.debug("Prepare the motor ports.");
for (GenericPort genericPort : genericPorts) {
// fetch the values from the generic port
if (genericPort.isSupportsMotorPort()) {
LOGGER.trace("The current port supports motor port: {}", genericPort);
MotorPort motorPort = new MotorPort(genericPort);
motorPort.setId(genericPort.getPortNumber());
motorPorts.add(motorPort);
}
else {
LOGGER.trace("The current port does not support motor port: {}", genericPort);
}
}
LOGGER.debug("Return the prepared motor ports: {}", motorPorts.size());
}
else {
LOGGER.debug("Return the cached motor ports, size: {}", motorPorts.size());
}
return Collections.unmodifiableList(motorPorts);
}
}
public List getSoundPorts() {
synchronized (genericPorts) {
if (CollectionUtils.isEmpty(soundPorts)) {
LOGGER.debug("Prepare the sound ports.");
for (GenericPort genericPort : genericPorts) {
// fetch the values from the generic port
if (genericPort.isSupportsSoundPort()) {
LOGGER.trace("The current port supports sound port: {}", genericPort);
SoundPort soundPort = new SoundPort(genericPort);
soundPort.setId(genericPort.getPortNumber());
soundPorts.add(soundPort);
}
else {
LOGGER.trace("The current port does not support sound port: {}", genericPort);
}
}
LOGGER.debug("Return the prepared sound ports: {}", soundPorts.size());
}
else {
LOGGER.debug("Return the cached sound ports, size: {}", soundPorts.size());
}
return Collections.unmodifiableList(soundPorts);
}
}
public boolean isUpdatable() {
return updatable;
}
public void setUpdatable(boolean updatable) {
this.updatable = updatable;
}
/**
* @return the bootloaderNode
*/
public boolean isBootloaderNode() {
return bootloaderNode;
}
/**
* @param bootloaderNode
* the bootloaderNode to set
*/
public void setBootloaderNode(boolean bootloaderNode) {
this.bootloaderNode = bootloaderNode;
}
/**
* @return the nodeHasError
*/
public boolean isNodeHasError() {
return nodeHasError || (sysError != null && !SysErrorEnum.BIDIB_ERR_NONE.equals(sysError));
}
/**
* @param ignoreSysError
* flag to allow ignore sys errors
* @return node has error flag set
*/
public boolean isNodeHasError(boolean ignoreSysError) {
if (ignoreSysError) {
return nodeHasError;
}
return isNodeHasError();
}
/**
* @return the nodeHasSysError
*/
public boolean isNodeHasSysError() {
return (sysError != null && !SysErrorEnum.BIDIB_ERR_NONE.equals(sysError));
}
/**
* @param nodeHasError
* the nodeHasError to set
*/
public void setNodeHasError(boolean nodeHasError) {
this.nodeHasError = nodeHasError;
if (!nodeHasError) {
setErrorState(null, null);
}
}
/**
* @param stall
* the stall flag to set
*/
public void setNodeIsStall(final boolean stall) {
LOGGER.warn("The node {} is stall: {}", node, stall);
this.isStall = stall;
// notify the console
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// ensure console is visible
ConsoleController.ensureConsoleVisible();
// add line
ConsoleModel.getConsoleModel().addConsoleLine(Color.black,
String.format("The node %s is %s", Node.this.toString(), stall ? "stall" : "not stall"));
}
});
}
/**
* @return the stall flag
*/
public boolean isNodeStall() {
return isStall;
}
/**
* @return the vendorCV
*/
public VendorCvData getVendorCV() {
return vendorCV;
}
/**
* @param vendorCV
* the vendorCV to set
*/
public void setVendorCV(VendorCvData vendorCV) {
LOGGER.debug("Set the vendorCV: {}", vendorCV);
this.vendorCV = vendorCV;
}
public CvDefinitionTreeTableModel getCvDefinitionTreeTableModel() {
if (treeModel == null) {
prepareVendorCVTree();
}
return treeModel;
}
public List getConfigVariables() {
return configVariables;
}
public Map getCvNumberToNodeMap() {
return cvNumberToNodeMap;
}
public void prepareVendorCVTree() {
if (vendorCV == null) {
LOGGER.info("No vendorCV definition available for node: {}", node);
return;
}
LOGGER.info("Prepare the vendorCV tree for node: {}", node);
cvRootNode = new DeviceNode(new Object[] { "root" });
treeModel = new CvDefinitionTreeTableModel(cvRootNode);
treeModel.setColumnIdentifiers(Arrays.asList(Resources.getString(getClass(), "column.cv"),
Resources.getString(getClass(), "column.description"), Resources.getString(getClass(), "column.value"),
Resources.getString(getClass(), "column.newvalue"), Resources.getString(getClass(), "column.mode")));
cvNumberToNodeMap = new LinkedHashMap();
List nodes = vendorCV.getVendorCV().getCVDefinition().getNode();
Map templatesMap = new HashMap();
if (vendorCV.getVendorCV().getTemplates() != null) {
for (TemplateType template : vendorCV.getVendorCV().getTemplates().getTemplate()) {
LOGGER.trace("Add template: {}", template.getName());
templatesMap.put(template.getName(), template);
}
LOGGER.trace("Prepared templatesMap: {}", templatesMap.keySet());
}
else {
LOGGER.info("No templates available.");
}
String lang = XmlLocaleUtils.getXmlLocale();
configVariables =
new CvDefinitionTreeHelper().addSubNodes(cvRootNode, nodes, treeModel, templatesMap, null, null, false,
lang, cvNumberToNodeMap);
}
private void fireAddressMessagesEnabledChanged(Boolean isAddressMessagesEnabled) {
for (NodeListener l : listeners) {
l.addressMessagesEnabledChanged(isAddressMessagesEnabled);
}
}
private void fireDccStartEnabledChanged(Boolean isDccStartEnabled) {
for (NodeListener l : listeners) {
l.dccStartEnabledChanged(isDccStartEnabled);
}
}
private void fireRailComPlusAvailableChanged(Boolean railComPlusAvailable) {
for (NodeListener l : listeners) {
l.railComPlusAvailableChanged(railComPlusAvailable);
}
}
private void firePomUpdateAvailableChanged(Boolean pomUpdateAvailable) {
for (NodeListener l : listeners) {
l.pomUpdateAvailableChanged(pomUpdateAvailable);
}
}
private void fireExternalStartEnabledChanged(Boolean isExternalStartEnabled) {
for (NodeListener l : listeners) {
l.externalStartEnabledChanged(isExternalStartEnabled);
}
}
private void fireFeedbackMessagesEnabledChanged(Boolean isFeedbackMessagesEnabled) {
for (NodeListener l : listeners) {
l.feedbackMessagesEnabledChanged(isFeedbackMessagesEnabled);
}
}
private void fireIdentifyStateChanged(IdentifyState identifyState) {
for (NodeListener l : listeners) {
l.identifyStateChanged(identifyState);
}
}
private void fireSysErrorChanged(SysErrorEnum sysError) {
for (NodeListener l : listeners) {
l.sysErrorChanged(sysError);
}
}
private void fireKeyMessagesEnabledChanged(Boolean isKeyMessagesEnabled) {
for (NodeListener l : listeners) {
l.keyMessagesEnabledChanged(isKeyMessagesEnabled);
}
}
private void fireLabelChanged(String label) {
for (NodeListener l : listeners) {
l.labelChanged(label);
}
}
public boolean equals(Object other) {
LOGGER.debug("equals, other: {}", other);
if (other != null) {
return ((Node) other).hashCode() == hashCode();
}
return false;
}
public int hashCode() {
if (node != null) {
return Long.valueOf(getNode().getUniqueId()).hashCode();
}
return super.hashCode();
}
public String toString() {
String result = null;
if (StringUtils.isNotBlank(label)) {
result = label;
}
else {
result = NodeUtils.getUniqueIdAsString(node.getUniqueId());
}
return result;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
LOGGER.info("The property has been changed, name: {}, new value: {}", evt.getPropertyName(), evt.getNewValue());
// TODO signal changes and error to UI
switch (evt.getPropertyName()) {
case GenericPort.PROPERTY_PORT_CONFIG_ERRORCODE:
break;
default:
break;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy