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

org.bidib.wizard.comm.CommunicationFactory Maven / Gradle / Ivy

There is a newer version: 2.0.0-M1
Show newest version
package org.bidib.wizard.comm;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.Semaphore;

import org.bidib.jbidibc.core.MessageListener;
import org.bidib.jbidibc.core.NodeListener;
import org.bidib.jbidibc.core.exception.NoAnswerException;
import org.bidib.jbidibc.core.node.listener.TransferListener;
import org.bidib.jbidibc.serial.scm.ScmSerialBidib;
import org.bidib.wizard.comm.bidib.BidibCommunication;
import org.bidib.wizard.comm.listener.CommunicationListener;
import org.bidib.wizard.locale.Resources;
import org.bidib.wizard.mvc.common.model.PreferencesPortType;
import org.bidib.wizard.mvc.preferences.model.Preferences;
import org.bidib.wizard.mvc.preferences.model.listener.PreferencesAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class CommunicationFactory {
    private static final Logger LOGGER = LoggerFactory.getLogger(CommunicationFactory.class.getName());

    private static Communication instance = null;

    private static Semaphore semaphore = new Semaphore(1);

    private static Set listeners = new LinkedHashSet();

    private static Set transferListeners = new LinkedHashSet();

    private static Set messageListeners = new LinkedHashSet();

    private static Set nodeListeners = new LinkedHashSet();

    // private static boolean ignoreWaitTimeout = true;

    static {
        LOGGER.info("The CommunicationFactory is instantiated.");
        Preferences.getInstance().addPropertyChangeListener(Preferences.PROPERTY_SELECTED_PORTTYPE,
            new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    PreferencesPortType portType = Preferences.getInstance().getSelectedPortType();

                    LOGGER.info("The selected port type has changed: {}", portType);
                    PreferencesPortType connectedPort = null;
                    boolean portClosed = false;
                    // check if the comm port has changed
                    synchronized (CommunicationFactory.class) {
                        try {
                            semaphore.acquire();
                            if (instance != null) {
                                connectedPort = instance.getConnectedPortType();
                                if (instance instanceof BidibCommunication) {
                                    // the real world communication
                                    BidibCommunication communication = (BidibCommunication) instance;
                                    if (!portType.equals(communication.getConnectedPortType())
                                        || (portType.getConnectionName() != null && !portType
                                            .getConnectionName().equals(connectedPort.getConnectionName()))) {
                                        // the comm port has changed
                                        LOGGER.info("Close the Bidib port.");
                                        try {
                                            ScmSerialBidib.getInstance().close();
                                        }
                                        catch (Exception ex) {
                                            LOGGER.warn("Close Bidib instance failed.", ex);
                                        }
                                        instance = null;
                                        portClosed = true;
                                        LOGGER.info("Released instance of BidibCommunication.");
                                    }
                                    else {
                                        LOGGER.info("The connected port was not changed.");
                                    }
                                }
                            }
                        }
                        catch (InterruptedException e) {
                            LOGGER.warn("Acquire semaphore failed.", e);
                            throw new RuntimeException(e);
                        }
                        finally {
                            semaphore.release();
                        }
                    }
                    if (connectedPort != null && portClosed) {
                        LOGGER.info("Port was closed: {}", connectedPort);
                        fireClosed(connectedPort.toString());
                    }
                }
            });

        Preferences.getInstance().addPreferencesListener(new PreferencesAdapter() {

            // @Override
            // public void dmxMappingOffsetChanged(int dmxMappingOffset) {
            // synchronized (CommunicationFactory.class) {
            // try {
            // semaphore.acquire();
            // if (instance != null) {
            // instance.setDmxMappingOffset(dmxMappingOffset);
            // }
            // }
            // catch (Exception ex) {
            // LOGGER.warn("Update DMX mapping offset failed.", ex);
            // }
            // finally {
            // semaphore.release();
            // }
            // }
            // }

            @Override
            public void resetReconnectDelayChanged(int resetReconnectDelay) {
                synchronized (CommunicationFactory.class) {
                    try {
                        semaphore.acquire();
                        if (instance != null) {
                            instance.setResetReconnectDelay(resetReconnectDelay);
                        }
                    }
                    catch (Exception ex) {
                        LOGGER.warn("Update reset reconnect delay failed.", ex);
                    }
                    finally {
                        semaphore.release();
                    }
                }
            }

            @Override
            public void responseTimeoutChanged(int responseTimeout) {
                synchronized (CommunicationFactory.class) {
                    try {
                        semaphore.acquire();
                        if (instance != null) {
                            instance.setResponseTimeout(responseTimeout);
                        }
                    }
                    catch (Exception ex) {
                        LOGGER.warn("Update the response timeout failed.", ex);
                    }
                    finally {
                        semaphore.release();
                    }
                }
            }

        });
    }

    private CommunicationFactory() {

    }

    public synchronized static Communication getInstance() {
        if (instance == null) {
            try {
                semaphore.acquire();

                fireStatus(Resources.getString(CommunicationFactory.class, "open-port"), -1);

                PreferencesPortType commPort = null;
                try {
                    commPort = Preferences.getInstance().getSelectedPortType();
                    LOGGER.debug("Start to open the Bidib port: {}", commPort);

                    if (commPort != null) {

                        instance = new BidibCommunication(commPort);
                        for (TransferListener transferListener : transferListeners) {
                            instance.addTransferListener(transferListener);
                        }

                        for (MessageListener messageListener : messageListeners) {
                            instance.addMessageListener(messageListener);
                        }

                        for (NodeListener nodeListener : nodeListeners) {
                            instance.addNodeListener(nodeListener);
                        }

                        instance.addCommunicationListener(new CommunicationListener() {
                            @Override
                            public void opened(String port) {
                                fireOpened(port);
                            }

                            @Override
                            public void closed(String port) {
                                fireClosed(port);
                            }

                            @Override
                            public void initialized() {
                                fireInitialized();
                            }

                            @Override
                            public void status(String statusText, int displayDuration) {
                                fireStatus(statusText, displayDuration);
                            }
                        });
                    }
                    else {
                        LOGGER.info("No comm port selected, do not create BidibCommunication.");
                        fireStatus(Resources.getString(CommunicationFactory.class, "no-port-selected"), -1);
                    }
                }
                catch (NoAnswerException ex) {
                    LOGGER.warn("Establish communication with interface failed.");
                    fireStatus(Resources.getString(CommunicationFactory.class, "establish-communication-failed"), -1);

                    // release the instance
                    instance = null;
                    throw ex;
                }
                catch (Exception e) {
                    LOGGER.warn("Open Bidib failed.", e);
                    fireStatus(Resources.getString(CommunicationFactory.class, "open-port-failed") + " " + commPort, -1);
                }
                // }
            }
            catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            finally {
                semaphore.release();
            }
        }
        return instance;
    }

    public static void addCommunicationListener(CommunicationListener listener) {
        LOGGER.info("Adding communication listener: {}", listener);
        synchronized (listeners) {
            listeners.add(listener);
        }
    }

    public static void addTransferListener(TransferListener listener) {
        LOGGER.info("Adding transfer listener: {}", listener);
        synchronized (transferListeners) {
            transferListeners.add(listener);
        }
    }

    public static void addMessageListener(MessageListener listener) {
        LOGGER.info("Adding message listener: {}", listener);
        synchronized (messageListeners) {
            messageListeners.add(listener);

            LOGGER.info("Currently registered messageListeners: {}", messageListeners);

            // if the instance is already assigned we must add the listener there
            try {
                semaphore.acquire();
                if (instance != null) {
                    LOGGER.info("Add the message listener to the exising instance.");
                    instance.addMessageListener(listener);
                }
            }
            catch (InterruptedException ex) {
                LOGGER.warn("Acquire semaphore to access instance failed.", ex);
            }
            finally {
                semaphore.release();
            }
        }
    }

    public static void removeMessageListener(MessageListener listener) {
        LOGGER.info("Remove message listener: {}", listener);
        synchronized (messageListeners) {
            messageListeners.remove(listener);
        }

        if (instance != null) {
            instance.removeMessageListener(listener);
        }
    }

    public static void addNodeListener(NodeListener listener) {
        LOGGER.info("Adding node listener: {}", listener);
        synchronized (nodeListeners) {
            nodeListeners.add(listener);
        }

        if (instance != null) {
            instance.addNodeListener(listener);
        }
    }

    public static void removeNodeListener(NodeListener listener) {
        LOGGER.info("Remove node listener: {}", listener);
        synchronized (nodeListeners) {
            nodeListeners.remove(listener);
        }

        if (instance != null) {
            instance.removeNodeListener(listener);
        }
    }

    public static void disconnect() {

        synchronized (CommunicationFactory.class) {
            LOGGER.info("Disconnect the communication.");
            try {
                semaphore.acquire();
                if (instance != null) {
                    instance.close();
                    instance = null;
                    LOGGER.info("Released instance of BidibCommunication.");
                }
            }
            catch (InterruptedException e) {
                LOGGER.warn("Acquire semaphore failed.", e);
                throw new RuntimeException(e);
            }
            finally {
                semaphore.release();
            }
        }
    }

    private static void fireOpened(String port) {
        for (CommunicationListener listener : listeners) {
            listener.opened(port);
        }
    }

    private static void fireClosed(String port) {
        for (CommunicationListener listener : listeners) {
            listener.closed(port);
        }
    }

    private static void fireInitialized() {
        for (CommunicationListener listener : listeners) {
            listener.initialized();
        }
    }

    private static void fireStatus(String statusText, int displayDuration) {
        for (CommunicationListener listener : listeners) {
            listener.status(statusText, displayDuration);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy