001package jmri.jmrix.mrc;
002
003import java.util.Date;
004import java.util.Vector;
005import org.slf4j.Logger;
006import org.slf4j.LoggerFactory;
007
008/**
009 * Converts Stream-based I/O to/from MRC messages. The "MrcInterface" side
010 * sends/receives message objects.
011 * <p>
012 * The connection to a MrcPortController is via a pair of *Streams, which then
013 * carry sequences of characters for transmission. Note that this processing is
014 * handled in an independent thread.
015 * <p>
016 * This handles the state transitions, based on the necessary state in each
017 * message.
018 *
019 * @author Bob Jacobsen Copyright (C) 2001
020 */
021public abstract class MrcTrafficController implements MrcInterface {
022
023    /**
024     * Create a new MrcTrafficController instance. Simple implementation.
025     */
026    public MrcTrafficController() {
027        super();
028    }
029
030    public void setCabNumber(int x) {
031        cabAddress = x;
032    }
033
034    int cabAddress = 0;
035
036    public int getCabNumber() {
037        return cabAddress;
038    }
039
040    // Abstract methods for the MrcInterface
041    @Override
042    abstract public boolean status();
043
044    @Override
045    abstract public void sendMrcMessage(MrcMessage m);
046
047    // The methods to implement adding and removing listeners
048    protected Vector<MrcTrafficListenerFilter> trafficListeners = new Vector<MrcTrafficListenerFilter>();
049
050    @Override
051    public synchronized void addTrafficListener(int mask, MrcTrafficListener l) {
052        if (l == null) {
053            throw new java.lang.NullPointerException();
054        }
055
056        // add only if not already registered
057        MrcTrafficListenerFilter adapter = new MrcTrafficListenerFilter(mask, l);
058        if (!trafficListeners.contains(adapter)) {
059            trafficListeners.addElement(adapter);
060        }
061    }
062
063    @Override
064    public synchronized void removeTrafficListener(int mask, MrcTrafficListener l) {
065        if (l == null) {
066            throw new java.lang.NullPointerException();
067        }
068
069        MrcTrafficListenerFilter filter = new MrcTrafficListenerFilter(mask, l);
070        if (trafficListeners.contains(filter)) {
071            trafficListeners.remove(trafficListeners.indexOf(filter)).setFilter(mask);
072        }
073    }
074
075    @Override
076    public synchronized void changeTrafficListener(int mask, MrcTrafficListener l) {
077        if (l == null) {
078            throw new java.lang.NullPointerException();
079        }
080
081        MrcTrafficListenerFilter filter = new MrcTrafficListenerFilter(mask, l);
082        if (trafficListeners.contains(filter)) {
083            trafficListeners.get(trafficListeners.indexOf(filter)).setFilter(mask);
084        }
085    }
086
087    @SuppressWarnings("unchecked")
088    public void notifyRcv(Date timestamp, MrcMessage m) {
089
090        // make a copy of the listener vector to synchronized not needed for transmit
091        Vector<MrcTrafficListenerFilter> v;
092        synchronized (this) {
093            v = (Vector<MrcTrafficListenerFilter>) trafficListeners.clone();
094        }
095        if (log.isDebugEnabled()) {
096            log.debug("notify of incoming Mrc packet: {}", m.toString());// NOI18N
097        }
098        // forward to all listeners
099        for (MrcTrafficListenerFilter adapter : v) {
100            adapter.fireRcv(timestamp, m);
101        }
102    }
103
104    @SuppressWarnings("unchecked")
105    public void notifyXmit(Date timestamp, MrcMessage m) {
106
107        // make a copy of the listener vector to synchronized not needed for transmit
108        Vector<MrcTrafficListenerFilter> v;
109        synchronized (this) {
110            v = (Vector<MrcTrafficListenerFilter>) trafficListeners.clone();
111        }
112        if (log.isDebugEnabled()) {
113            log.debug("notify of send Mrc packet: {}", m.toString());// NOI18N
114        }
115        // forward to all listeners
116        for (MrcTrafficListenerFilter adapter : v) {
117            adapter.fireXmit(timestamp, m);
118        }
119    }
120
121    /**
122     * Is there a backlog of information for the outbound link? This includes
123     * both in the program (e.g. the outbound queue) and in the command station
124     * interface (e.g. flow control from the port).
125     *
126     * @return true if busy, false if nothing waiting to send
127     */
128    abstract public boolean isXmtBusy();
129
130    /**
131     * Reset statistics (received message count, transmitted message count,
132     * received byte count).
133     */
134    public void resetStatistics() {
135        receivedMsgCount = 0;
136        transmittedMsgCount = 0;
137        receivedByteCount = 0;
138    }
139
140    /**
141     * Monitor the number of MRC messaages received across the interface. This
142     * includes the messages this client has sent.
143     *
144     * @return count of messages received
145     */
146    public int getReceivedMsgCount() {
147        return receivedMsgCount;
148    }
149    protected int receivedMsgCount = 0;
150
151    /**
152     * Monitor the number of bytes in MRC messaages received across the
153     * interface. This includes the messages this client has sent.
154     *
155     * @return count of bytes in received messages
156     */
157    public int getReceivedByteCount() {
158        return receivedByteCount;
159    }
160    protected int receivedByteCount = 0;
161
162    /**
163     * Monitor the number of MRC messages transmitted across the interface.
164     *
165     * @return count of messages sent
166     */
167    public int getTransmittedMsgCount() {
168        return transmittedMsgCount;
169    }
170    protected int transmittedMsgCount = 0;
171
172    public MrcSystemConnectionMemo getAdapterMemo() {
173        return adaptermemo;
174    }
175
176    public void setAdapterMemo(MrcSystemConnectionMemo memo) {
177        adaptermemo = memo;
178    }
179
180    MrcSystemConnectionMemo adaptermemo;
181
182    public String getUserName() {
183        if (adaptermemo == null) {
184            return "MRC"; // NOI18N
185        }
186        return adaptermemo.getUserName();
187    }
188
189    public String getSystemPrefix() {
190        if (adaptermemo == null) {
191            return "M"; // NOI18N
192        }
193        return adaptermemo.getSystemPrefix();
194    }
195
196    private final static Logger log = LoggerFactory.getLogger(MrcTrafficController.class);
197
198}