001package jmri.jmrix.internal;
002
003import java.util.Comparator;
004import java.util.ResourceBundle;
005
006import jmri.*;
007import jmri.jmrix.debugthrottle.DebugThrottleManager;
008import jmri.managers.DefaultPowerManager;
009import jmri.managers.DefaultProgrammerManager;
010import jmri.progdebugger.DebugProgrammerManager;
011import jmri.util.NamedBeanPreferNumericComparator;
012
013/**
014 * Lightweight class to denote that a system is active, and provide general
015 * information.
016 * <p>
017 * Things this needed to do:
018 * <ul>
019 * <li>One of these must be automatically, transparently available - this is
020 * done by inheriting from jmri.InstanceManagerAutoDefault
021 * <li>It must be possible to have more than one of these, so you can have
022 * multiple internal systems defined - each one keeps internal references to its
023 * objects
024 * <li>It must make sure that its objects are available individually through the
025 * instance manager.
026 * <li>But it also has to handle the ProxyManager special cases in the
027 * InstanceManager
028 * </ul>
029 *
030 * @author Bob Jacobsen Copyright (C) 2010, 2016
031 */
032public class InternalSystemConnectionMemo extends jmri.jmrix.DefaultSystemConnectionMemo implements jmri.InstanceManagerAutoDefault {
033
034    public InternalSystemConnectionMemo(String prefix, String name, boolean defaultInstanceType) {
035        super(prefix, name);
036        InstanceManager.store(this, InternalSystemConnectionMemo.class); // also register as specific type
037        register();
038        this.defaultInstanceType = defaultInstanceType;
039    }
040
041    public InternalSystemConnectionMemo(String prefix, String name) {
042        this(prefix, name, true);
043    }
044
045    public InternalSystemConnectionMemo(boolean defaultInstanceType) {
046        this("I", "Internal", defaultInstanceType);
047    }
048
049    // invoked by i.e. InstanceManager via the InstanceManagerAutoDefault
050    // mechanism, this creates a partial system
051    public InternalSystemConnectionMemo() {
052        this(true);
053    }
054
055    boolean configured = false;
056
057    // if true, this is the default Internal instance, which 
058    // only provides a subset of types
059    boolean defaultInstanceType = false;
060
061    /**
062     * Configure the common managers for Internal connections. This puts the
063     * common manager config in one place.
064     * <p>
065     * Note: The Proxy system can cause some managers to be created early. We
066     * don't call configureManagers in that case, as it causes an infinite loop.
067     */
068    public void configureManagers() {
069
070        log.debug("Do configureManagers - doesn't pre-build anything");
071        if (configured) {
072            log.warn("configureManagers called for a second time", new Exception("traceback"));
073        }
074        configured = true;
075    }
076
077    public InternalSensorManager getSensorManager() {
078        InternalSensorManager sensorManager = (InternalSensorManager) classObjectMap.get(SensorManager.class);
079        if(sensorManager == null ) {
080            log.debug("Create InternalSensorManager \"{}\" by request", getSystemPrefix());
081            sensorManager = new InternalSensorManager(this);
082            store(sensorManager,SensorManager.class);
083            // special due to ProxyManager support
084            InstanceManager.setSensorManager(sensorManager);
085        }
086        return sensorManager;
087    }
088
089    public InternalLightManager getLightManager() {
090        InternalLightManager lightManager = (InternalLightManager) classObjectMap.get(LightManager.class);
091        if(lightManager == null) {
092            log.debug("Create InternalLightManager by request");
093            lightManager = new InternalLightManager(this);
094            store(lightManager,LightManager.class);
095            // special due to ProxyManager support
096            InstanceManager.setLightManager(lightManager);
097        }
098        return lightManager;
099    }
100
101    public InternalReporterManager getReporterManager() {
102        InternalReporterManager reporterManager = (InternalReporterManager) classObjectMap.get(ReporterManager.class);
103        if(reporterManager == null ) {
104            log.debug("Create InternalReporterManager by request");
105            reporterManager = new InternalReporterManager(this);
106            store(reporterManager,ReporterManager.class);
107            // special due to ProxyManager support
108            InstanceManager.setReporterManager(reporterManager);
109        }
110        return reporterManager;
111    }
112
113    public InternalTurnoutManager getTurnoutManager() {
114        InternalTurnoutManager turnoutManager = (InternalTurnoutManager) classObjectMap.get(TurnoutManager.class);
115        if(turnoutManager == null ) {
116            log.debug("Create InternalTurnoutManager \"{}\" by request", getSystemPrefix());
117            turnoutManager = new InternalTurnoutManager(this);
118            store(turnoutManager,TurnoutManager.class);
119            // special due to ProxyManager support
120            InstanceManager.setTurnoutManager(turnoutManager);
121        }
122        return turnoutManager;
123    }
124
125    public InternalMeterManager getMeterManager() {
126        InternalMeterManager meterManager = (InternalMeterManager) classObjectMap.get(MeterManager.class);
127        if (meterManager == null) {
128            log.debug("Create InternalMeterManager by request", getSystemPrefix());
129            meterManager = new InternalMeterManager(this);
130            // special due to ProxyManager support
131            InstanceManager.setMeterManager(meterManager);
132        }
133        return meterManager;
134    }
135
136    public InternalAnalogIOManager getAnalogIOManager() {
137        InternalAnalogIOManager analogIOManager = (InternalAnalogIOManager) classObjectMap.get(AnalogIOManager.class);
138        if (analogIOManager == null) {
139            log.debug("Create InternalAnalogIOManager by request", getSystemPrefix());
140            analogIOManager = new InternalAnalogIOManager(this);
141            // special due to ProxyManager support
142            InstanceManager.setAnalogIOManager(analogIOManager);
143        }
144        return analogIOManager;
145    }
146
147    public InternalStringIOManager getStringIOManager() {
148        InternalStringIOManager stringIOManager = (InternalStringIOManager) classObjectMap.get(StringIOManager.class);
149        if (stringIOManager == null) {
150            log.debug("Create InternalStringIOManager by request", getSystemPrefix());
151            stringIOManager = new InternalStringIOManager(this);
152            // special due to ProxyManager support
153            InstanceManager.setStringIOManager(stringIOManager);
154        }
155        return stringIOManager;
156    }
157
158    public DefaultPowerManager getPowerManager() {
159        return (DefaultPowerManager) classObjectMap.computeIfAbsent(PowerManager.class, (Class c) -> {
160            log.debug("Create DefaultPowerManager by request");
161            PowerManager powerManager = new jmri.managers.DefaultPowerManager(this);
162            jmri.InstanceManager.store(powerManager, PowerManager.class);
163            return powerManager;
164        });
165    }
166
167    @Override
168    public InternalConsistManager getConsistManager() {
169        if (defaultInstanceType) {
170            return null;
171        }
172        return (InternalConsistManager) classObjectMap.computeIfAbsent((ConsistManager.class), (Class c) -> {
173            log.debug("Create InternalConsistManager by request");
174            ConsistManager consistManager = new InternalConsistManager();
175            InstanceManager.store(consistManager, jmri.ConsistManager.class);
176            return consistManager;
177        });
178    }
179
180    public DebugThrottleManager getThrottleManager() {
181        if (defaultInstanceType) {
182            return null;
183        }
184        return (DebugThrottleManager) classObjectMap.computeIfAbsent(ThrottleManager.class, ( Class c) -> {
185            log.debug("Create DebugThrottleManager by request");
186            // Install a debug throttle manager
187            ThrottleManager throttleManager = new jmri.jmrix.debugthrottle.DebugThrottleManager(this);
188            jmri.InstanceManager.setThrottleManager(throttleManager);
189            return throttleManager;
190        });
191    }
192
193    public DebugProgrammerManager getProgrammerManager() {
194        if (defaultInstanceType) {
195            return null;
196        }
197        return (DebugProgrammerManager) classObjectMap.computeIfAbsent(DefaultProgrammerManager.class,
198                (Class c) -> {
199                    // Install a debug programmer
200                    log.debug("Create DebugProgrammerManager by request");
201                    return new DebugProgrammerManager(this);
202                });
203    }
204
205    @Override
206    public boolean provides(Class<?> type) {
207        if (getDisabled()) {
208            return false;
209        }
210
211        if (!configured) {
212            configureManagers();
213        }
214
215        if (type.equals(jmri.SensorManager.class)) {
216            return true;
217        }
218        if (type.equals(jmri.LightManager.class)) {
219            return true;
220        }
221        if (type.equals(jmri.ReporterManager.class)) {
222            return true;
223        }
224        if (type.equals(jmri.TurnoutManager.class)) {
225            return true;
226        }
227
228        if (!defaultInstanceType) {
229            if (type.equals(jmri.PowerManager.class)) {
230                return true;
231            }
232
233            if (type.equals(jmri.GlobalProgrammerManager.class)) {
234                return getProgrammerManager().isGlobalProgrammerAvailable();
235            }
236            if (type.equals(jmri.AddressedProgrammerManager.class)) {
237                return getProgrammerManager().isAddressedModePossible();
238            }
239
240            if (type.equals(jmri.ThrottleManager.class)) {
241                return true;
242            }
243            if (type.equals(jmri.ConsistManager.class)) {
244                return true;
245            }
246        }
247
248        return super.provides(type);
249    }
250
251    @SuppressWarnings("unchecked")
252    @Override
253    public <T> T get(Class<?> type) {
254        if (getDisabled()) {
255            return null;
256        }
257
258        if (!configured) {
259            configureManagers();
260        }
261
262        if (type.equals(jmri.SensorManager.class)) {
263            return (T) getSensorManager();
264        }
265        if (type.equals(jmri.LightManager.class)) {
266            return (T) getLightManager();
267        }
268        if (type.equals(jmri.ReporterManager.class)) {
269            return (T) getReporterManager();
270        }
271        if (type.equals(jmri.TurnoutManager.class)) {
272            return (T) getTurnoutManager();
273        }
274
275        if (!defaultInstanceType) {
276            if (type.equals(jmri.PowerManager.class)) {
277                return (T) getPowerManager();
278            }
279
280            if (type.equals(jmri.GlobalProgrammerManager.class)) {
281                return (T) getProgrammerManager();
282            }
283            if (type.equals(jmri.AddressedProgrammerManager.class)) {
284                return (T) getProgrammerManager();
285            }
286
287            if (type.equals(jmri.ThrottleManager.class)) {
288                return (T) getThrottleManager();
289            }
290            if (type.equals(jmri.ConsistManager.class)) {
291                return (T) getConsistManager();
292            }
293        }
294
295        return super.get(type);
296    }
297
298    @Override
299    protected ResourceBundle getActionModelResourceBundle() {
300        // No actions to add at start up
301        return null;
302    }
303
304    @Override
305    public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) {
306        return new NamedBeanPreferNumericComparator<>();
307    }
308
309    @Override
310    public void dispose() {
311        SensorManager sensorManager = (SensorManager) classObjectMap.get(SensorManager.class);
312        if (sensorManager != null) {
313            sensorManager.dispose();
314        }
315
316        TurnoutManager turnoutManager = (TurnoutManager) classObjectMap.get(TurnoutManager.class);
317        if (turnoutManager != null) {
318            turnoutManager.dispose();
319        }
320        super.dispose();
321    }
322
323    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(InternalSystemConnectionMemo.class);
324
325}