org.bidib.wizard.localhost.client.controller.LocalHostClientController Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bidibwizard-localhost-client Show documentation
Show all versions of bidibwizard-localhost-client Show documentation
jBiDiB BiDiB Wizard localhost client POM
package org.bidib.wizard.localhost.client.controller;
import java.util.List;
import java.util.Map;
import javax.swing.SwingUtilities;
import org.apache.commons.collections4.CollectionUtils;
import org.bidib.jbidibc.messages.enums.MessageClassEnum;
import org.bidib.jbidibc.messages.utils.NodeUtils;
import org.bidib.wizard.api.model.NodeInterface;
import org.bidib.wizard.api.model.NodeListProvider;
import org.bidib.wizard.api.model.listener.DefaultNodeListListener;
import org.bidib.wizard.api.model.listener.NodeListListener;
import org.bidib.wizard.client.common.view.DockKeys;
import org.bidib.wizard.client.common.view.DockUtils;
import org.bidib.wizard.core.model.connection.ConnectionRegistry;
import org.bidib.wizard.core.service.ConnectionService;
import org.bidib.wizard.localhost.NodeSubscriptionData;
import org.bidib.wizard.localhost.LocalHostSubscriptionEventProvider;
import org.bidib.wizard.localhost.client.controller.listener.LocalHostClientControllerListener;
import org.bidib.wizard.localhost.client.model.SubscribedClientTableModel;
import org.bidib.wizard.localhost.client.view.LocalHostClientView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.vlsolutions.swing.docking.Dockable;
import com.vlsolutions.swing.docking.DockableState;
import com.vlsolutions.swing.docking.DockingConstants;
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 io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
public class LocalHostClientController implements LocalHostClientControllerListener {
private static final Logger LOGGER = LoggerFactory.getLogger(LocalHostClientController.class);
private final DockingDesktop desktop;
private LocalHostClientView localHostClientView;
private SubscribedClientTableModel subscribedClientTableModel;
@Autowired
private ConnectionService connectionService;
@Autowired(required = false)
private List localHostSubscriptionEventProviders;
private CompositeDisposable compDisposable;
private final NodeListProvider nodeListProvider;
private NodeListListener nodeListListener;
public LocalHostClientController(final DockingDesktop desktop, final NodeListProvider nodeListProvider) {
this.desktop = desktop;
this.nodeListProvider = nodeListProvider;
}
public void start() {
// check if the nodes client view is already opened
String searchKey = DockKeys.LOCALHOST_CLIENT_VIEW;
LOGGER.info("Search for view with key: {}", searchKey);
Dockable view = desktop.getContext().getDockableByKey(searchKey);
if (view != null) {
LOGGER.info("Select the existing LocalHost client view instead of open a new one.");
DockUtils.selectWindow(view);
return;
}
this.subscribedClientTableModel = new SubscribedClientTableModel();
LOGGER.info("Create new LocalHostClientView.");
this.localHostClientView = new LocalHostClientView(desktop, this, subscribedClientTableModel);
this.localHostClientView.initComponents();
// add dockable
DockableState[] dockables = desktop.getDockables();
LOGGER.info("Current dockables: {}", new Object[] { dockables });
if (dockables.length > 1) {
DockableState tabPanelNodeDetails = null;
// search the node details tab panel
for (DockableState dockable : dockables) {
if (DockKeys.DOCKKEY_TAB_PANEL.equals(dockable.getDockable().getDockKey())) {
LOGGER.info("Found the tab panel dockable.");
tabPanelNodeDetails = dockable;
break;
}
}
Dockable dock = desktop.getDockables()[1].getDockable();
if (tabPanelNodeDetails != null) {
LOGGER.info("Add the localHostClientView next to the node details panel.");
dock = tabPanelNodeDetails.getDockable();
TabbedDockableContainer container = DockingUtilities.findTabbedDockableContainer(dock);
int order = 0;
if (container != null) {
order = container.getTabCount();
}
LOGGER.info("Add new nodesClientView at order: {}", order);
desktop.createTab(dock, localHostClientView, order, true);
}
else {
desktop.split(dock, localHostClientView, DockingConstants.SPLIT_RIGHT);
}
}
else {
desktop.addDockable(localHostClientView, RelativeDockablePosition.RIGHT);
}
// create the nodeList listener
this.nodeListListener = new DefaultNodeListListener() {
@Override
public void listNodeAdded(NodeInterface node) {
LOGGER.info("The nodelist has a new node: {}", node);
}
@Override
public void listNodeRemoved(NodeInterface node) {
LOGGER.info("The nodelist has a node removed: {}", node);
nodeLost(node);
}
};
// register as nodeList listener at the main model
this.nodeListProvider.addNodeListListener(nodeListListener);
// we must check if the connection is established already
if (connectionService.isConnected(ConnectionRegistry.CONNECTION_ID_MAIN)) {
subscribeLocalHostSubscriberChanges();
}
this.connectionService.subscribeConnectionStatusChanges(ci -> {
if (ConnectionRegistry.CONNECTION_ID_MAIN.equals(ci.getConnectionId())) {
switch (ci.getConnectionState().getActualPhase()) {
case CONNECTED:
subscribeLocalHostSubscriberChanges();
break;
case DISCONNECTED:
unsubscribeLocalHostSubscriberChanges();
break;
default:
break;
}
}
}, th -> {
});
}
private void subscribeLocalHostSubscriberChanges() {
LOGGER.info("subscribeLocalHostSubscriberChanges.");
if (this.compDisposable != null) {
LOGGER.info("The subscription for localhost subscriber changes is already done.");
return;
}
// create new composite disposable
this.compDisposable = new CompositeDisposable();
if (CollectionUtils.isNotEmpty(localHostSubscriptionEventProviders)) {
localHostSubscriptionEventProviders.forEach(provider -> {
LOGGER.info("Current localHostSubscriptionEventProvider: {}", provider);
Disposable dispSubscriptionEvents = provider.subscribeSubscriberEvents(se -> {
LOGGER.info("Received a subscription event: {}", se);
switch (se.getAction()) {
case add:
internalAddSubscriber(se.getNodeAddress(), se.getUniqueId(), se.getMessageClasses());
break;
case remove:
internalRemoveSubscriber(se.getNodeAddress(), se.getUniqueId(), se.getMessageClasses());
break;
default:
break;
}
}, error -> {
LOGGER.warn("The status event signalled a failure: {}", error);
});
compDisposable.add(dispSubscriptionEvents);
// fetch the current subscribers
final Map> subscriptions = provider.getSubscriptions();
subscriptions.forEach((mc, addresses) -> {
addresses.forEach(addr -> internalAddSubscriber(addr.getSubscriberAddress(), addr.getSubscriberUniqueId(), addr.getSubscription()));
});
});
}
else {
LOGGER.warn("No localHostSubscriptionEventProvider instances available.");
}
}
private void unsubscribeLocalHostSubscriberChanges() {
LOGGER.info("unsubscribeLocalHostSubscriberChanges.");
if (this.compDisposable == null) {
LOGGER.info("The subsription for localhost subscriber changes does not exist.");
return;
}
if (this.compDisposable != null) {
this.compDisposable.dispose();
this.compDisposable = null;
}
}
private void internalAddSubscriber(byte[] nodeAddress, Long uniqueId, Integer messageClass) {
LOGGER
.info("Add subscriber, address: {}, messageClass: {}", NodeUtils.formatAddressLong(nodeAddress),
messageClass);
this.subscribedClientTableModel.addSubscribedClient(nodeAddress, uniqueId, messageClass);
}
private void internalRemoveSubscriber(byte[] nodeAddress, Long uniqueId, Integer messageClass) {
LOGGER
.info("Remove subscriber, address: {}, messageClass: {}", NodeUtils.formatAddressLong(nodeAddress),
messageClass);
this.subscribedClientTableModel.removeSubscribedClient(nodeAddress, uniqueId, messageClass);
}
private void nodeLost(final NodeInterface node) {
SwingUtilities.invokeLater(() -> internalRemoveSubscriber(node.getAddr(), null, null));
}
@Override
public void viewClosed() {
LOGGER.info("View is closed.");
unsubscribeLocalHostSubscriberChanges();
try {
// remove node listener from communication factory
if (this.nodeListListener != null) {
this.nodeListProvider.removeNodeListListener(nodeListListener);
}
}
catch (Exception ex) {
LOGGER.warn("Unregister controller as node listener failed.", ex);
}
this.nodeListListener = null;
}
}