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    @Override
135    public <T> T get(Class<T> T) {
136        if (getDisabled()) {
137            return null;
138        }
139        if(T.equals(jmri.ReporterManager.class)){
140            return super.get(T);
141        }
142        if(T.equals(jmri.SensorManager.class)){
143            return super.get(T);
144        }
145        if (_xnettunnel!=null && _xnettunnel.getStreamPortController().getSystemConnectionMemo().provides(T) ) {
146            // delegate to the XPressNet tunnel.
147            return _xnettunnel.getStreamPortController().getSystemConnectionMemo().get(T);
148        }
149        if (_loconettunnel!=null && _loconettunnel.getStreamPortController().getSystemConnectionMemo().provides(T) ) {
150            // delegate to the LocoNet tunnel.
151            return _loconettunnel.getStreamPortController().getSystemConnectionMemo().get(T);
152        }
153        return null; // nothing, by default
154    }
155
156    /**
157     * Configure the common managers for z21 connections. This puts the common
158     * manager config in one place.
159     */
160    @Override
161    public void configureManagers() {
162        log.debug("Called Configure Managers");
163
164        RocoZ21CommandStation z21CommandStation = getRocoZ21CommandStation();
165
166        // set the broadcast flags so we get messages we may want to hear
167        z21CommandStation.setXPressNetMessagesFlag(true);
168        z21CommandStation.setXPressNetLocomotiveMessagesFlag(true);
169        z21CommandStation.setLocoNetMessagesFlag(true);
170        z21CommandStation.setLocoNetLocomotiveMessagesFlag(true);
171        z21CommandStation.setLocoNetTurnoutMessagesFlag(true);
172
173        // and forward the flags to the command station
174        _tc.sendz21Message(Z21Message.getLanSetBroadcastFlagsRequestMessage(
175                           z21CommandStation.getZ21BroadcastFlags()),null);
176
177        // add an LocoNet Tunnel
178        _loconettunnel = (Z21LocoNetTunnel) classObjectMap.computeIfAbsent(Z21LocoNetTunnel.class, (Class<?> c) -> new Z21LocoNetTunnel(this));
179
180        // add an XpressNet Tunnel
181        _xnettunnel = (Z21XPressNetTunnel) classObjectMap.computeIfAbsent(Z21XPressNetTunnel.class, (Class<?> c) -> new Z21XPressNetTunnel(this));
182
183        // set up the Reporter Manager
184        jmri.InstanceManager.setReporterManager(getReporterManager());
185
186        // set up the SensorManager
187        jmri.InstanceManager.setSensorManager(getSensorManager());
188
189        // but make sure the LocoNet memo is set (for one feedback message).
190        XNetProgrammerManager xpm = _xnettunnel.getStreamPortController().getSystemConnectionMemo().getProgrammerManager();
191        if ( xpm instanceof Z21XNetProgrammerManager) {
192            ((Z21XNetProgrammerManager) xpm).setLocoNetMemo(_loconettunnel.getStreamPortController().getSystemConnectionMemo());
193        }
194
195        // setup the PredefinedMeters
196        createPredefinedMeters();
197
198        // setup the HeartBeat
199        getHeartBeat();
200
201        register();
202   }
203
204    @Override
205    protected ResourceBundle getActionModelResourceBundle() {
206        return ResourceBundle.getBundle("jmri.jmrix.roco.z21.z21ActionListBundle");
207    }
208
209    @Override
210    public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) {
211        return new NamedBeanComparator<>();
212    }
213
214    /**
215     * Provide access to the Command Station for this particular connection.
216     * <p>
217     * NOTE: Command Station defaults to NULL
218     * @return command station, may be null.
219     */
220    public CommandStation getCommandStation() {
221        return get(CommandStation.class);
222    }
223
224    public void setCommandStation(CommandStation c) {
225        store(c,CommandStation.class);
226    }
227
228    /**
229     * Provide access to the Roco Z21 Command Station for this particular
230     * connection.
231     * <p>
232     * NOTE: Command Station defaults to NULL
233     * @return Roco Z21 Command Station, may be null.
234     */
235    public RocoZ21CommandStation getRocoZ21CommandStation() {
236        return (RocoZ21CommandStation) classObjectMap.computeIfAbsent(RocoZ21CommandStation.class, (Class<?> c) -> new RocoZ21CommandStation());
237    }
238
239    public void setRocoZ21CommandStation(RocoZ21CommandStation c) {
240        store(c,RocoZ21CommandStation.class);
241    }
242
243    protected Z21PredefinedMeters predefinedMeters;
244
245    /**
246     * Provide access to the Roco Z21 MultiMeter for this particular
247     * connection.
248     * <p>
249     * NOTE: PredefinedMeters defaults to NULL
250     * @return PredefinedMeters, creates new if null.
251     */
252    public Z21PredefinedMeters createPredefinedMeters() {
253        if (getDisabled()) {
254            return null;
255        }
256        if (predefinedMeters == null) {
257            InstanceManager.setMeterManager(new jmri.managers.AbstractMeterManager(this));
258            predefinedMeters = new Z21PredefinedMeters(this);
259        }
260        return predefinedMeters;
261    }
262
263    /**
264     * Provide access to the Z21HeartBeat instance for this connection.
265     * <p>
266     * NOTE: HeartBeat defaults to NULL
267     * @return the HeartBeat, creates new if null.
268     */
269    public Z21HeartBeat getHeartBeat() {
270        if(heartBeat == null){
271           heartBeat = new Z21HeartBeat(this);
272        }
273        return heartBeat;
274    }
275
276    private Z21HeartBeat heartBeat = null;
277
278    void shutdownTunnel(){
279        if (_xnettunnel!=null) {
280            _xnettunnel.dispose();
281            _xnettunnel=null;
282        }
283        if (_loconettunnel!=null) {
284            _loconettunnel.dispose();
285            _loconettunnel=null;
286        }
287    }
288
289    @Override
290    public void dispose() {
291        if(heartBeat!=null) {
292           heartBeat.dispose();
293        }
294        shutdownTunnel();
295        InstanceManager.deregister(this, Z21SystemConnectionMemo.class);
296        if (predefinedMeters != null) {
297            predefinedMeters.dispose();
298        }
299        super.dispose();
300    }
301
302    private final static Logger log = LoggerFactory.getLogger(Z21SystemConnectionMemo.class);
303
304}