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

org.bidib.wizard.localhost.client.controller.LocalHostClientController Maven / Gradle / Ivy

There is a newer version: 2.0.29
Show newest version
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;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy