001package jmri.jmrix.lenz;
002
003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
004import org.slf4j.Logger;
005import org.slf4j.LoggerFactory;
006
007import java.awt.event.ActionEvent;
008
009/**
010 * This class provides a base implementation for Command Station/interface
011 * dependent initialization for XpressNet. It adds the appropriate Managers via
012 * the Initialization Manager based on the Command Station Type.
013 *
014 * @author Paul Bender Copyright (C) 2003-2010
015 * @deprecated since 4.21.1.  Use {@link XNetInitializationManager} instead.
016 */
017@Deprecated
018public abstract class AbstractXNetInitializationManager {
019
020    protected final XNetSystemConnectionMemo systemMemo;
021
022    /**
023     * Define timeout used during initialization
024     * @return timout value in milliseconds
025     */
026    protected int getInitTimeout() {
027        return 30000;
028    }
029
030    public AbstractXNetInitializationManager(XNetSystemConnectionMemo memo) {
031        /* spawn a thread to request version information and wait for the 
032         command station to respond */
033        if (log.isDebugEnabled()) {
034            log.debug("Starting XpressNet Initialization Process");
035        }
036        systemMemo = memo;
037        new XNetInitializer(this);
038
039        // Since we can't currently reconfigure the user interface after  
040        // initialization, We need to wait for the initialization thread
041        // to finish before we can continue.  The wait  can be removed IF 
042        // we revisit the GUI initialization process.
043        synchronized (this) {
044            log.debug("start wait");
045            new jmri.util.WaitHandler(this);
046            log.debug("end wait");
047        }
048
049        init();
050    }
051
052    protected abstract void init();
053
054    /* Internal class to configure the XNet implementation */
055    protected class XNetInitializer implements XNetListener {
056
057        private final javax.swing.Timer initTimer; // Timer used to let he
058        // command station response time 
059        // out, and configure the defaults.
060
061        private final Object parent;
062
063        public XNetInitializer(Object Parent) {
064
065            parent = Parent;
066
067            initTimer = setupInitTimer();
068
069            // Register as an XpressNet Listener
070            systemMemo.getXNetTrafficController().addXNetListener(XNetInterface.CS_INFO, this);
071
072            //Send Information request to LI100/LI100
073         /* First, we need to send a request for the Command Station
074             hardware and software version */
075            XNetMessage msg = XNetMessage.getCSVersionRequestMessage();
076            //Then Send the version request to the controller
077            systemMemo.getXNetTrafficController().sendXNetMessage(msg, this);
078        }
079
080        protected javax.swing.Timer setupInitTimer() {
081            // Initialize and start initialization timeout timer.
082            javax.swing.Timer retVal = new javax.swing.Timer(getInitTimeout(),
083                    (ActionEvent e) -> {
084                                    /* If the timer times out, notify any 
085                                     waiting objects, and dispose of
086                                     this thread */
087                                    if (log.isDebugEnabled()) {
088                                        log.debug("Timeout waiting for Command Station Response");
089                                    }
090                                    finish();
091                                });
092            retVal.setInitialDelay(getInitTimeout());
093            retVal.start();
094            return retVal;
095        }
096
097        @SuppressFBWarnings(value = "NO_NOTIFY_NOT_NOTIFYALL", justification = "There should only ever be one thread waiting for this method (the designated parent, which started the thread).")
098        private void finish() {
099            initTimer.stop();
100            // Notify the parent
101            try {
102                synchronized (parent) {
103                    parent.notify();
104                }
105            } catch (Exception e) {
106                log.error("Exception {] while notifying initialization thread.",e);
107            }
108            if (log.isDebugEnabled()) {
109                log.debug("Notification Sent");
110            }
111            // Then dispose of this object
112            dispose();
113        }
114
115        // listen for the responses from the LI100/LI101
116        @Override
117        public void message(XNetReply l) {
118            // Check to see if this is a response with the Command Station 
119            // Version Info
120            if (l.getElement(0) == XNetConstants.CS_SERVICE_MODE_RESPONSE &&
121                    l.getElement(1) == XNetConstants.CS_SOFTWARE_VERSION) {
122                // This is the Command Station Software Version Response
123                    systemMemo.getXNetTrafficController()
124                            .getCommandStation()
125                            .setCommandStationSoftwareVersion(l);
126                    systemMemo.getXNetTrafficController()
127                            .getCommandStation()
128                            .setCommandStationType(l);
129                    finish();
130            }
131        }
132
133        // listen for the messages to the LI100/LI101
134        @Override
135        public void message(XNetMessage l) {
136            // we aren't concerned with incoming messages in this class.
137        }
138
139        // Handle a timeout notification
140        @Override
141        public void notifyTimeout(XNetMessage msg) {
142            if (log.isDebugEnabled()) {
143                log.debug("Notified of timeout on message {}",msg);
144            }
145        }
146
147        public void dispose() {
148            systemMemo.getXNetTrafficController().removeXNetListener(XNetInterface.CS_INFO, this);
149        }
150    }
151
152    private static final Logger log = LoggerFactory.getLogger(AbstractXNetInitializationManager.class);
153
154}