001package jmri.jmrix.roco.z21;
002
003import java.util.Comparator;
004import java.util.ResourceBundle;
005
006import jmri.*;
007import jmri.jmrix.ConfiguringSystemConnectionMemo;
008import jmri.jmrix.lenz.XNetProgrammerManager;
009import jmri.util.NamedBeanComparator;
010
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014/**
015 * Lightweight class to denote that a system is active, and provide general
016 * information.
017 * <p>
018 * Objects of specific subtypes are registered in the instance manager to
019 * activate their particular system.
020 *
021 * @author Bob Jacobsen Copyright (C) 2010 copied from NCE into PowerLine for
022 * multiple connections by
023 * @author Ken Cameron Copyright (C) 2011 copied from PowerLine into z21 by
024 * @author Paul Bender Copyright (C) 2013,2019,2020
025 */
026public class Z21SystemConnectionMemo extends jmri.jmrix.DefaultSystemConnectionMemo implements ConfiguringSystemConnectionMemo {
027
028    private Z21XPressNetTunnel _xnettunnel = null;
029    private Z21LocoNetTunnel _loconettunnel = null;
030
031    public Z21SystemConnectionMemo() {
032        this("Z", "Z21");
033    }
034
035    public Z21SystemConnectionMemo(String prefix, String userName) {
036        super(prefix, userName);
037        InstanceManager.store(this, Z21SystemConnectionMemo.class); // also register as specific type
038        init();
039    }
040
041    /*
042     * Override the init function for any subtype specific
043     * registration into init.  init is called by the generic contstructor.
044     */
045    protected void init() {
046        // create and register the ComponentFactory
047        InstanceManager.store(componentFactory = new jmri.jmrix.roco.z21.swing.Z21ComponentFactory(this),
048                jmri.jmrix.swing.ComponentFactory.class);
049    }
050
051    jmri.jmrix.swing.ComponentFactory componentFactory = null;
052
053    /**
054     * Traffic Controller for this instance.
055     * @param newtc Z21 traffic controller.
056     */
057    public void setTrafficController(Z21TrafficController newtc) {
058        _tc = newtc;
059    }
060
061    public Z21TrafficController getTrafficController() {
062        return _tc;
063    }
064    private Z21TrafficController _tc = null;
065
066    /**
067     * Reporter Manager for this instance.
068     * @param rm reporter manager.
069     */
070    public void setReporterManager(Z21ReporterManager rm){
071        store(rm, ReporterManager.class);
072    }
073
074    public Z21ReporterManager getReporterManager() {
075        return (Z21ReporterManager) classObjectMap.computeIfAbsent(ReporterManager.class, (Class c) -> { return new Z21ReporterManager(this); });
076    }
077
078    /**
079     * SensorManager for this instance.
080     * @param sm sensor manager.
081     */
082    public void setSensorManager(Z21SensorManager sm){
083        store(sm,SensorManager.class);
084    }
085
086    public Z21SensorManager getSensorManager() {
087        return (Z21SensorManager) classObjectMap.computeIfAbsent(SensorManager.class, (Class c) -> { return new Z21SensorManager(this); });
088    }
089
090    public XNetProgrammerManager getProgrammerManager() {
091        if (_xnettunnel!=null) {
092            // delegate to the XPressNet tunnel.
093            return _xnettunnel.getStreamPortController().getSystemConnectionMemo().getProgrammerManager();
094        }
095        return null;
096    }
097
098    public void setProgrammerManager(XNetProgrammerManager p) {
099    }
100
101    /**
102     * Tells which managers this class provides.
103     */
104    @Override
105    public boolean provides(Class<?> type) {
106        if (getDisabled()) {
107            return false;
108        }
109        if (type.equals(jmri.ReporterManager.class)){
110           return true;
111        }
112        if (type.equals(jmri.SensorManager.class)){
113           return true;
114        }
115        if (_xnettunnel!=null) {
116            // delegate to the XPressNet tunnel.
117            if(_xnettunnel.getStreamPortController().getSystemConnectionMemo().provides(type)) {
118               return true;
119            } // don't return false here, let the following code run 
120        }
121        if (_loconettunnel!=null) {
122            // delegate to the LocoNet tunnel.
123            if(_loconettunnel.getStreamPortController().getSystemConnectionMemo().provides(type)) {
124               return true;
125            } // don't return false here, let the following code run
126            
127        }
128        return super.provides(type); // nothing, by default
129    }
130
131    /**
132     * Provide manager by class.
133     */
134    @SuppressWarnings("unchecked")  // xpressnet code managed type for cast
135    @Override
136    public <T> T get(Class<?> T) {
137        if (getDisabled()) {
138            return null;
139        }
140        if(T.equals(jmri.ReporterManager.class)){
141            return super.get(T);
142        }
143        if(T.equals(jmri.SensorManager.class)){
144            return super.get(T);
145        }
146        if (_xnettunnel!=null && _xnettunnel.getStreamPortController().getSystemConnectionMemo().provides(T) ) {
147            // delegate to the XPressNet tunnel.
148            return _xnettunnel.getStreamPortController().getSystemConnectionMemo().get(T);
149        }
150        if (_loconettunnel!=null && _loconettunnel.getStreamPortController().getSystemConnectionMemo().provides(T) ) {
151            // delegate to the LocoNet tunnel.
152            return _loconettunnel.getStreamPortController().getSystemConnectionMemo().get(T);
153        }
154        return null; // nothing, by default
155    }
156
157    /**
158     * Configure the common managers for z21 connections. This puts the common
159     * manager config in one place.
160     */
161    @Override
162    public void configureManagers() {
163        log.debug("Called Configure Managers");
164
165        RocoZ21CommandStation z21CommandStation = getRocoZ21CommandStation();
166
167        // set the broadcast flags so we get messages we may want to hear
168        z21CommandStation.setXPressNetMessagesFlag(true);
169        z21CommandStation.setXPressNetLocomotiveMessagesFlag(true);
170        z21CommandStation.setLocoNetMessagesFlag(true);
171        z21CommandStation.setLocoNetLocomotiveMessagesFlag(true);
172        z21CommandStation.setLocoNetTurnoutMessagesFlag(true);
173
174        // and forward the flags to the command station
175        _tc.sendz21Message(Z21Message.getLanSetBroadcastFlagsRequestMessage(
176                           z21CommandStation.getZ21BroadcastFlags()),null);
177
178        // add an LocoNet Tunnel
179        _loconettunnel = (Z21LocoNetTunnel) classObjectMap.computeIfAbsent(Z21LocoNetTunnel.class, (Class c) -> new Z21LocoNetTunnel(this));
180
181        // add an XpressNet Tunnel
182        _xnettunnel = (Z21XPressNetTunnel) classObjectMap.computeIfAbsent(Z21XPressNetTunnel.class, (Class c) -> new Z21XPressNetTunnel(this));
183
184        // set up the Reporter Manager
185        jmri.InstanceManager.setReporterManager(getReporterManager());
186
187        // set up the SensorManager
188        jmri.InstanceManager.setSensorManager(getSensorManager());
189
190        // but make sure the LocoNet memo is set (for one feedback message).
191        XNetProgrammerManager xpm = _xnettunnel.getStreamPortController().getSystemConnectionMemo().getProgrammerManager();
192        if ( xpm instanceof Z21XNetProgrammerManager) {
193            ((Z21XNetProgrammerManager) xpm).setLocoNetMemo(_loconettunnel.getStreamPortController().getSystemConnectionMemo());
194        }
195
196        // setup the PredefinedMeters
197        createPredefinedMeters();
198
199        // setup the HeartBeat
200        getHeartBeat();
201
202        register();
203   }
204
205    @Override
206    protected ResourceBundle getActionModelResourceBundle() {
207        return ResourceBundle.getBundle("jmri.jmrix.roco.z21.z21ActionListBundle");
208    }
209
210    @Override
211    public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) {
212        return new NamedBeanComparator<>();
213    }
214
215    /**
216     * Provide access to the Command Station for this particular connection.
217     * <p>
218     * NOTE: Command Station defaults to NULL
219     * @return command station, may be null.
220     */
221    public CommandStation getCommandStation() {
222        return get(CommandStation.class);
223    }
224
225    public void setCommandStation(CommandStation c) {
226        store(c,CommandStation.class);
227    }
228
229    /**
230     * Provide access to the Roco Z21 Command Station for this particular
231     * connection.
232     * <p>
233     * NOTE: Command Station defaults to NULL
234     * @return Roco Z21 Command Station, may be null.
235     */
236    public RocoZ21CommandStation getRocoZ21CommandStation() {
237        return (RocoZ21CommandStation) classObjectMap.computeIfAbsent(RocoZ21CommandStation.class, (Class c) -> new RocoZ21CommandStation());
238    }
239
240    public void setRocoZ21CommandStation(RocoZ21CommandStation c) {
241        store(c,RocoZ21CommandStation.class);
242    }
243
244    protected Z21PredefinedMeters predefinedMeters;
245    
246    /**
247     * Provide access to the Roco Z21 MultiMeter for this particular
248     * connection.
249     * <p>
250     * NOTE: PredefinedMeters defaults to NULL
251     * @return PredefinedMeters, creates new if null.
252     */
253    public Z21PredefinedMeters createPredefinedMeters() {
254        if (getDisabled()) {
255            return null;
256        }
257        if (predefinedMeters == null) {
258            InstanceManager.setMeterManager(new jmri.managers.AbstractMeterManager(this));
259            predefinedMeters = new Z21PredefinedMeters(this);
260        }
261        return predefinedMeters;
262    }
263
264    /**
265     * Provide access to the Z21HeartBeat instance for this connection.
266     * <p>
267     * NOTE: HeartBeat defaults to NULL
268     * @return the HeartBeat, creates new if null.
269     */
270    public Z21HeartBeat getHeartBeat() {
271        if(heartBeat == null){
272           heartBeat = new Z21HeartBeat(this);
273        }
274        return heartBeat;
275    }
276    
277    private Z21HeartBeat heartBeat = null;
278
279    void shutdownTunnel(){
280        if (_xnettunnel!=null) {
281            _xnettunnel.dispose();
282            _xnettunnel=null;
283        }
284    }
285
286    @Override
287    public void dispose() {
288        if(heartBeat!=null) {
289           heartBeat.dispose();
290        }
291        shutdownTunnel();
292        InstanceManager.deregister(this, Z21SystemConnectionMemo.class);
293        if (predefinedMeters != null) {
294            predefinedMeters.dispose();
295        }
296        super.dispose();
297    }
298
299    private final static Logger log = LoggerFactory.getLogger(Z21SystemConnectionMemo.class);
300
301}