001package jmri.jmrix.lenz;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006/**
007 * Implements an XNetInterface by doing a scatter-gather to another, simpler
008 * implementation.
009 * <p>
010 * This is intended for remote operation, where only one copy of each message
011 * should go to/from another node. By putting a LnTrafficRouter implementation
012 * at the remote node, all of the routing of messages to multiple consumers can
013 * be done without traffic over the connection.
014 *
015 * @author Bob Jacobsen Copyright (C) 2002
016 * @author Paul Bender Copyright (C) 2004-2010
017 */
018public class XNetTrafficRouter extends XNetTrafficController implements XNetListener {
019
020    public XNetTrafficRouter(LenzCommandStation pCommandStation) {
021        super(pCommandStation);
022    }
023
024    // The methods to implement the XNetInterface for clients.
025    // These use the parent implementations of listeners, addXNetListener,
026    // removeXNetListener, notify
027    boolean connected = false;
028
029    @Override
030    public boolean status() {
031        return connected;
032    }
033
034
035    /**
036     * Store the last sender
037     */
038    XNetListener lastSender = null;
039
040    /**
041     * Forward a preformatted XNetMessage to the actual interface.
042     *
043     * @param m Message to send; will be updated with CRC
044     */
045    @Override
046    public void sendXNetMessage(XNetMessage m, XNetListener replyTo) {
047        lastSender = replyTo;
048        destination.sendXNetMessage(m, replyTo);
049    }
050
051    /**
052     * Receive an XNet message from upstream and forward it to all the local
053     * clients.
054     */
055    @Override
056    public void message(XNetReply m) {
057        notify(m);
058    }
059
060    /**
061     * Listen for the messages to the LI100/LI101.
062     */
063    @Override
064    public void message(XNetMessage l) {
065    }
066
067    // Handle a timeout notification
068    @Override
069    public void notifyTimeout(XNetMessage msg) {
070        if (log.isDebugEnabled()) {
071            log.debug("Notified of timeout on message{}", msg.toString());
072        }
073    }
074
075    // methods to connect/disconnect to a source of data in another
076    // XNetInterface
077    private XNetInterface destination = null;
078
079    /**
080     * Make connection to existing XNetInterface object for upstream
081     * communication.
082     *
083     * @param i Interface to be connected
084     */
085    public void connect(XNetInterface i) {
086        destination = i;
087        connected = true;
088        i.addXNetListener(XNetInterface.ALL, this);
089    }
090
091    /**
092     * Break connection to upstream LocoNetInterface object. Once broken,
093     * attempts to send via "message" member will fail.
094     *
095     * @param i previously connected interface
096     */
097    public void disconnectPort(XNetInterface i) {
098        if (destination != i) {
099            log.warn("disconnectPort: disconnect called from non-connected PortController");
100        }
101        destination = null;
102        connected = false;
103    }
104
105    /**
106     * Forward an XNetMessage to all registered listeners.
107     *
108     * @param m Message to forward. Listeners should not modify it!
109     */
110    protected void notify(XNetReply m) {
111        notifyReply(m, lastSender);
112        lastSender = null;
113    }
114
115    private static final Logger log = LoggerFactory.getLogger(XNetTrafficRouter.class);
116
117}