001package jmri.jmrix.can.cbus; 002 003import java.util.List; 004import java.util.ResourceBundle; 005 006import javax.annotation.Nonnull; 007 008import jmri.*; 009import jmri.jmrix.can.CanSystemConnectionMemo; 010import jmri.jmrix.can.cbus.simulator.CbusSimulator; 011import jmri.jmrix.can.cbus.node.CbusNodeTableDataModel; 012import jmri.jmrix.can.cbus.eventtable.CbusEventTableDataModel; 013import jmri.jmrix.can.cbus.swing.cbusslotmonitor.CbusSlotMonitorDataModel; 014 015/** 016 * Does configuration for MERG CBUS CAN-based communications implementations. 017 * <hr> 018 * This file is part of JMRI. 019 * <p> 020 * JMRI is free software; you can redistribute it and/or modify it under the 021 * terms of version 2 of the GNU General Public License as published by the Free 022 * Software Foundation. See the "COPYING" file for a copy of this license. 023 * <p> 024 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 025 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 026 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 027 * 028 * @author Bob Jacobsen Copyright (C) 2009 029 * @author Steve Young Copyright (C) 2022 030 */ 031public class CbusConfigurationManager extends jmri.jmrix.can.ConfigurationManager implements Disposable { 032 033 /** 034 * Create a new CbusConfigurationManager. 035 * A Supporting class to configure the {@link jmri.jmrix.can.CanSystemConnectionMemo} 036 * for the {@link jmri.jmrix.can.cbus} classes. 037 * @param memo Connection to configure. 038 */ 039 public CbusConfigurationManager(@Nonnull CanSystemConnectionMemo memo) { 040 super(memo); 041 storeToMemoAndInstance(CbusConfigurationManager.this, CbusConfigurationManager.class); 042 cf = new jmri.jmrix.can.cbus.swing.CbusComponentFactory(adapterMemo); 043 InstanceManager.store(cf, jmri.jmrix.swing.ComponentFactory.class); 044 } 045 046 private final jmri.jmrix.swing.ComponentFactory cf; 047 048 // configureManagers() startup order 049 private static final List<Class<?>> DEFAULT_CLASSES = List.of( 050 CbusPreferences.class, 051 PowerManager.class, 052 SensorManager.class, 053 // SensorManager before TurnoutManager so that listener can be added 054 CommandStation.class, 055 // CommandStation before TurnoutManager so that Raw Turnout Operator available 056 TurnoutManager.class, 057 ThrottleManager.class, 058 CbusPredefinedMeters.class, 059 ReporterManager.class, 060 LightManager.class, 061 CabSignalManager.class, 062 // Clock Control initialised last so CbusSensorManager exists, otherwise 063 // InternalSensorManager is deafult SensorManager when ISCLOCKRUNNING is provided. 064 ClockControl.class); 065 066 /** 067 * {@inheritDoc} 068 */ 069 @Override 070 public void configureManagers() { 071 072 for (Class<?> listClass : DEFAULT_CLASSES ) { 073 provide(listClass); 074 } 075 076 // We register a programmer based on whether the hardware is available, 077 // not whether the functionality is available 078 CbusDccProgrammerManager pm = getProgrammerManager(); 079 if ( pm !=null ) { 080 if (pm.isAddressedModeHardwareAvailable()) { 081 storeToMemoAndInstance(pm, AddressedProgrammerManager.class); 082 } 083 if (pm.isGlobalProgrammerHardwareAvailable()) { 084 storeToMemoAndInstance(pm, GlobalProgrammerManager.class); 085 } 086 } 087 088 if (getConsistManager() != null) { 089 storeToMemoAndInstance(getConsistManager(), ConsistManager.class); 090 } 091 092 // kick-start cbus sim tools ( Dummy Command Station etc. ) if using loopback connection 093 if ( adapterMemo.getTrafficController() instanceof jmri.jmrix.can.adapters.loopback.LoopbackTrafficController) { 094 adapterMemo.get( CbusSimulator.class); 095 } 096 097 } 098 099 /** 100 * Tells which managers this class provides. 101 * {@inheritDoc} 102 * @param type Class type to check 103 * @return true if supported; false if not 104 */ 105 @Override 106 public boolean provides(Class<?> type) { 107 if (adapterMemo.getDisabled()) { 108 return false; 109 } else if (type.equals(AddressedProgrammerManager.class)) { 110 return getProgrammerManager().isAddressedModePossible(); 111 } else if (type.equals(GlobalProgrammerManager.class)) { 112 return getProgrammerManager().isGlobalProgrammerAvailable(); 113 } else if (type.equals(ConsistManager.class)) { 114 return true; 115 } else if (type.equals(CbusSimulator.class)) { 116 return true; 117 } else if (type.equals(CbusSlotMonitorDataModel.class)) { 118 return true; 119 } else { 120 return DEFAULT_CLASSES.contains(type); 121 } 122 } 123 124 /** 125 * {@inheritDoc} 126 */ 127 @SuppressWarnings("unchecked") 128 @Override 129 public <T> T get(Class<?> T) { 130 if (adapterMemo.getDisabled()) { 131 return null; 132 } else if (T.equals(AddressedProgrammerManager.class) 133 && getProgrammerManager().isAddressedModePossible()) { 134 return (T) getProgrammerManager(); 135 } else if (T.equals(GlobalProgrammerManager.class) 136 && getProgrammerManager().isGlobalProgrammerAvailable()) { 137 return (T) getProgrammerManager(); 138 } else if (T.equals(ConsistManager.class)) { 139 return (T) getConsistManager(); 140 } else if (T.equals(CbusSimulator.class)) { 141 return provide(T); 142 } else if (T.equals(CbusSlotMonitorDataModel.class)) { 143 return provide(T); 144 } else if ( DEFAULT_CLASSES.contains(T) ) { 145 return provide(T); 146 } 147 return null; // nothing, by default 148 } 149 150 private CbusDccProgrammerManager programmerManager; 151 152 private CbusDccProgrammerManager getProgrammerManager() { 153 if (programmerManager == null && !adapterMemo.getDisabled()) { 154 programmerManager = new CbusDccProgrammerManager( 155 new CbusDccProgrammer(adapterMemo), adapterMemo); 156 } 157 return programmerManager; 158 } 159 160 protected CbusConsistManager consistManager = null; 161 162 /** 163 * Get the ConsistManager, creating one if neccessary. 164 * 165 * Only enable it if we definitely have a command station. 166 * 167 * @return ConsistManager object 168 */ 169 private ConsistManager getConsistManager() { 170 if ( adapterMemo.getDisabled() ) { 171 return null; 172 } 173 if (consistManager == null) { 174 consistManager = new CbusConsistManager(get(CommandStation.class)); 175 if (adapterMemo.getProgModeSwitch() == ProgModeSwitch.EITHER) { 176 // Could be either programmer or command station 177 if (getProgrammerManager().isAddressedModePossible()) { 178 // We have a command station so enable the ConsistManager 179 consistManager.setEnabled(true); 180 } else { 181 // Disable for now, may be enabled later if user switches modes, avoid returning a null manager 182 consistManager.setEnabled(false); 183 } 184 } else { 185 // Command station is always avaliable 186 consistManager.setEnabled(true); 187 } 188 } 189 return consistManager; 190 } 191 192 /** 193 * Provide a new Class instance. 194 * <p> 195 * NOT for general use outside of this class, although public so that 196 * classes like CbusEventTablePane can get a CbusEventTableDataModel 197 * when started. 198 * <p> 199 * If a class is NOT auto-created by the normal get, 200 * it can be provided with this method. 201 * Adds provided class to memo class object map, 202 * AND InstanceManager. 203 * @param <T> class type. 204 * @param T class type. 205 * @return class object, or null if unavailable. 206 */ 207 public <T> T provide(@Nonnull Class<?> T){ 208 if (adapterMemo.getDisabled()) { 209 return null; 210 } 211 T existing = adapterMemo.getFromMap(T); // if already in object map, use it 212 if ( existing !=null ) { 213 return existing; 214 } 215 if (T.equals(CbusNodeTableDataModel.class)) { 216 storeToMemoAndInstance(new CbusNodeTableDataModel(adapterMemo,10), CbusNodeTableDataModel.class); 217 } else if (T.equals(CbusEventTableDataModel.class)) { 218 storeToMemoAndInstance(new CbusEventTableDataModel(adapterMemo,10), CbusEventTableDataModel.class); 219 } else if (T.equals(CbusPreferences.class)) { 220 storeToMemoAndInstance(new CbusPreferences(), CbusPreferences.class); 221 } else if (T.equals(PowerManager.class)) { 222 storeToMemoAndInstance(new CbusPowerManager(adapterMemo), PowerManager.class); 223 } else if (T.equals(CommandStation.class)) { 224 storeToMemoAndInstance(new CbusCommandStation(adapterMemo), CommandStation.class); 225 } else if (T.equals(ThrottleManager.class)) { 226 storeToMemoAndInstance(new CbusThrottleManager(adapterMemo), ThrottleManager.class); 227 } else if (T.equals(CabSignalManager.class)) { 228 storeToMemoAndInstanceDefault(new CbusCabSignalManager(adapterMemo), CabSignalManager.class); 229 } else if (T.equals(ClockControl.class) ) { 230 storeToMemoAndInstanceDefault(new CbusClockControl(adapterMemo), ClockControl.class); 231 } else if (T.equals(SensorManager.class) ) { 232 adapterMemo.store(new CbusSensorManager(adapterMemo), SensorManager.class); 233 InstanceManager.setSensorManager(adapterMemo.getFromMap(T)); 234 } else if (T.equals(TurnoutManager.class) ) { 235 adapterMemo.store(new CbusTurnoutManager(adapterMemo), TurnoutManager.class); 236 InstanceManager.setTurnoutManager(adapterMemo.getFromMap(T)); 237 } else if (T.equals(ReporterManager.class) ) { 238 adapterMemo.store(new CbusReporterManager(adapterMemo), ReporterManager.class); 239 InstanceManager.setReporterManager(adapterMemo.getFromMap(T)); 240 } else if (T.equals(LightManager.class) ) { 241 adapterMemo.store(new CbusLightManager(adapterMemo), LightManager.class); 242 InstanceManager.setLightManager(adapterMemo.getFromMap(T)); 243 } else if (T.equals(CbusPredefinedMeters.class) ) { 244 InstanceManager.setMeterManager(new jmri.managers.AbstractMeterManager(adapterMemo)); 245 storeToMemoAndInstance(new CbusPredefinedMeters(adapterMemo), CbusPredefinedMeters.class); 246 } 247 else if (T.equals(CbusSimulator.class)) { 248 storeToMemoAndInstance(new CbusSimulator(adapterMemo), CbusSimulator.class); 249 } 250 else if (T.equals(CbusSlotMonitorDataModel.class)) { 251 storeToMemoAndInstance(new CbusSlotMonitorDataModel(adapterMemo), CbusSlotMonitorDataModel.class); 252 } 253 return adapterMemo.getFromMap(T); // if class not in map, class not provided. 254 } 255 256 private <T> void storeToMemoAndInstance(@Nonnull T item, @Nonnull Class<T> type){ 257 adapterMemo.store(item, type); // store with memo 258 InstanceManager.store(item, type); // and with InstanceManager 259 } 260 261 private <T> void storeToMemoAndInstanceDefault(@Nonnull T item, @Nonnull Class<T> type){ 262 adapterMemo.store(item, type); // store with memo 263 InstanceManager.setDefault( type, item); // and with InstanceManager 264 } 265 266 public <T> void disposeOf(@Nonnull T item, @Nonnull Class<T> type ) { 267 InstanceManager.deregister(item, type); 268 adapterMemo.deregister(item, type); 269 } 270 271 /** 272 * {@inheritDoc} 273 */ 274 @Override 275 public void dispose() { 276 277 // classed stored in the memo classObjectMap will be deregisted from 278 // InstanceManager on memo disposal, and will also have their 279 // dispose method called if they implement jmri.Disposable. 280 281 InstanceManager.deregister(cf, jmri.jmrix.swing.ComponentFactory.class); 282 283 if (consistManager != null) { 284 InstanceManager.deregister(consistManager, ConsistManager.class); 285 } 286 if (programmerManager != null) { 287 programmerManager.dispose(); 288 } 289 InstanceManager.deregister(this, CbusConfigurationManager.class); 290 } 291 292 /** 293 * {@inheritDoc} 294 */ 295 @Override 296 protected ResourceBundle getActionModelResourceBundle() { 297 return ResourceBundle.getBundle("jmri.jmrix.can.CanActionListBundle"); 298 } 299 300 // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusConfigurationManager.class); 301 302}