org.bidib.wizard.mvc.position.model.FeedbackPositionModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bidibwizard-client Show documentation
Show all versions of bidibwizard-client Show documentation
jBiDiB BiDiB Wizard Client Application POM
package org.bidib.wizard.mvc.position.model;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.function.IntFunction;
import java.util.stream.Stream;
import javax.swing.SwingUtilities;
import org.apache.commons.collections4.CollectionUtils;
import org.bidib.jbidibc.core.schema.bidibbase.BaseLabel;
import org.bidib.jbidibc.messages.enums.PositionLocationEnum;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.bidib.wizard.api.model.NodeInterface;
import org.bidib.wizard.api.model.PositionAddressData;
import org.bidib.wizard.api.model.PositionFeedbackPort;
import org.bidib.wizard.api.model.RfBasisNode;
import org.bidib.wizard.api.model.listener.PortListListener;
import org.bidib.wizard.model.status.FeedbackPortStatus;
import org.bidib.wizard.mvc.position.controller.FeedbackPositionStatusChangeProvider;
import org.bidib.wizard.mvc.position.model.listener.FeedbackPositionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jgoodies.binding.beans.Model;
public class FeedbackPositionModel extends Model implements FeedbackPositionStatusChangeProvider {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory.getLogger(FeedbackPositionModel.class);
public static final String PROPERTY_PORT_LIST = "portList";
public static final String PROPERTY_RFBASIS_NODES = "rfBasisNodes";
private PropertyChangeListener pclFeedbackPorts;
private final List feedbackPositionListeners = new LinkedList<>();
private List portList = new LinkedList<>();
private final List portListListeners = new LinkedList<>();
private List rfBasisNodes = new LinkedList<>();
private long uniqueId;
private final PropertyChangeListener pclBaseNumber;
private final IntFunction labelFunction;
public FeedbackPositionModel(final IntFunction labelFunction) {
LOGGER.info("Create new instance of FeedbackPositionModel.");
this.labelFunction = labelFunction;
pclFeedbackPorts = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
LOGGER.debug("Property has changed, evt: {}", evt);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (PortListListener listener : portListListeners) {
LOGGER.debug("Notify listener that the ports have changed: {}", listener);
listener.listChanged();
}
}
});
}
};
addPropertyChangeListener(pclFeedbackPorts);
pclBaseNumber = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
LOGGER.info("The base number has changed on node: {}", evt.getSource());
if (evt.getSource() instanceof NodeInterface) {
NodeInterface rfBasisNode = (NodeInterface) evt.getSource();
checkForSingleOrMasterBasis(rfBasisNode);
}
}
};
}
private void checkForSingleOrMasterBasis(final NodeInterface rfBasisNode) {
int baseNumber = rfBasisNode.getBaseNumber();
LOGGER.info("Set the base number on the rfBasisNode: {}", baseNumber);
if (baseNumber == 0 || baseNumber == 1) {
LOGGER.info("This is the single or master basis.");
long uniqueId = rfBasisNode.getUniqueId();
LOGGER.info("Set the uniqueId in the feedbackPositionModel: {}", ByteUtils.formatHexUniqueId(uniqueId));
setNodeUnique(uniqueId);
}
}
/**
* Set the uniqueId of the single or master basis.
*
* @param uniqueId
* the uniqueId
*/
public void setNodeUnique(long uniqueId) {
LOGGER.info("Set the uniqueId: {}", uniqueId);
this.uniqueId = uniqueId;
}
private long getUniqueId() {
return uniqueId;
}
public void addPosition(
byte[] address, int decoderAddress, PositionLocationEnum locationType, int locationAddress,
byte[] extendedData) {
LOGGER
.info("Add position, locationType: {}, locationAddress: {}, decoderAddress: {}", locationType,
locationAddress, decoderAddress);
synchronized (portList) {
// try to find the previous assigned position for the decoder address
Stream prevPort = portList.stream().filter(p -> {
for (PositionAddressData ad : p.getAddresses()) {
if (decoderAddress == ad.getDecoderAddress()) {
return true;
}
}
return false;
});
long lastSeenTimestamp = System.currentTimeMillis();
PositionAddressData positionAddressData = new PositionAddressData(decoderAddress, lastSeenTimestamp);
prevPort.iterator().forEachRemaining(p -> {
p.removeAddress(positionAddressData);
if (!p.hasAddresses()) {
p.setStatus(FeedbackPortStatus.FREE);
}
});
// search for existing location address in list
Optional port =
portList.stream().filter(p -> p.getId() == locationAddress).findFirst();
if (port.isPresent()) {
port.get().addAddress(positionAddressData);
port.get().setStatus(FeedbackPortStatus.OCCUPIED);
}
else {
PositionFeedbackPort newPort = new PositionFeedbackPort(locationAddress);
if (getUniqueId() > 0) {
try {
BaseLabel label = labelFunction.apply(newPort.getId());
LOGGER.info("New port, id: {}, current label: {}", newPort.getId(), label);
newPort.setLabel(label != null ? label.getLabel() : null);
}
catch (Exception ex) {
LOGGER.warn("Set the label of the feedback position port failed.", ex);
}
}
else {
LOGGER.info("No feedbackPortLabels or no uniqueId.");
}
newPort.addAddress(positionAddressData);
newPort.setStatus(FeedbackPortStatus.OCCUPIED);
LOGGER.debug("Created new port to add to portList: {}", newPort);
portList.add(newPort);
}
}
firePropertyChange(PROPERTY_PORT_LIST, null, portList);
}
public List getPortList() {
return portList;
}
/**
* @return the rfBasisNodes
*/
public List getRfBasisNodes() {
synchronized (rfBasisNodes) {
return Collections.unmodifiableList(rfBasisNodes);
}
}
/**
* @param rfBasisNodes
* the rfBasisNodes to set
*/
public void setRfBasisNodes(List rfBasisNodes) {
synchronized (rfBasisNodes) {
this.rfBasisNodes.clear();
if (CollectionUtils.isNotEmpty(rfBasisNodes)) {
this.rfBasisNodes.addAll(rfBasisNodes);
// add listener
for (RfBasisNode rfBasisNode : rfBasisNodes) {
addBaseNumberListener(rfBasisNode);
}
}
}
firePropertyChange(PROPERTY_RFBASIS_NODES, null, this.rfBasisNodes);
}
/**
* @param rfBasisNode
* the rfBasisNode to add
*/
public void addRfBasisNode(final RfBasisNode rfBasisNode) {
synchronized (rfBasisNodes) {
this.rfBasisNodes.add(rfBasisNode);
addBaseNumberListener(rfBasisNode);
checkForSingleOrMasterBasis(rfBasisNode.getNode());
}
firePropertyChange(PROPERTY_RFBASIS_NODES, null, rfBasisNodes);
}
/**
* @param rfBasisNode
* the rfBasisNode to remove
*/
public void removeRfBasisNode(final RfBasisNode rfBasisNode) {
synchronized (rfBasisNodes) {
this.rfBasisNodes.remove(rfBasisNode);
removeBaseNumberListener(rfBasisNode);
}
firePropertyChange(PROPERTY_RFBASIS_NODES, null, rfBasisNodes);
}
private void addBaseNumberListener(final RfBasisNode rfBasisNode) {
rfBasisNode.getNode().addPropertyChangeListener(NodeInterface.PROPERTY_BASENUMBER, pclBaseNumber);
}
private void removeBaseNumberListener(final RfBasisNode rfBasisNode) {
rfBasisNode.getNode().removePropertyChangeListener(NodeInterface.PROPERTY_BASENUMBER, pclBaseNumber);
}
@Override
public void addFeedbackPortListener(final FeedbackPositionListener feedbackPositionListener) {
feedbackPositionListeners.add(feedbackPositionListener);
}
@Override
public void removeFeedbackPortListener(final FeedbackPositionListener feedbackPositionListener) {
feedbackPositionListeners.remove(feedbackPositionListener);
}
@Override
public void addPortListListener(PortListListener portListListener) {
portListListeners.add(portListListener);
}
@Override
public void removePortListListener(PortListListener portListListener) {
portListListeners.remove(portListListener);
}
public void clearAddressesAndPortStatus() {
synchronized (portList) {
for (PositionFeedbackPort port : portList) {
port.setStatus(FeedbackPortStatus.FREE);
port.clear();
}
}
firePropertyChange(PROPERTY_PORT_LIST, null, portList);
}
public void validatePositions(final List outdatedPorts, long timeout) {
synchronized (portList) {
for (PositionFeedbackPort port : portList) {
if (port.getStatus() == FeedbackPortStatus.OCCUPIED) {
boolean outdated = port.isOutdated(timeout);
if (outdated) {
outdatedPorts.add(port);
}
}
}
}
}
}