001package jmri.jmrix.dcc4pc; 002 003import java.util.Comparator; 004import java.util.ResourceBundle; 005import java.util.function.Supplier; 006 007import jmri.*; 008import jmri.jmrix.ConfiguringSystemConnectionMemo; 009import jmri.jmrix.DefaultSystemConnectionMemo; 010import jmri.jmrix.SystemConnectionMemoManager; 011import jmri.util.NamedBeanComparator; 012 013/** 014 * Lightweight class to denote that a system is active, and provide general 015 * information. 016 * <p> 017 * Objects of specific subtypes are registered in the instance manager to 018 * activate their particular system. 019 * 020 * @author Kevin Dickerson Copyright (C) 2012 021 */ 022public class Dcc4PcSystemConnectionMemo extends DefaultSystemConnectionMemo implements ConfiguringSystemConnectionMemo { 023 024 public Dcc4PcSystemConnectionMemo(Dcc4PcTrafficController tc) { 025 super("D", "Dcc4Pc"); 026 this.tc = tc; 027 tc.setAdapterMemo(this); 028 } 029 030 public Dcc4PcSystemConnectionMemo() { 031 super("D", "Dcc4Pc"); 032 InstanceManager.store(this, Dcc4PcSystemConnectionMemo.class); 033 //Needs to be implemented 034 InstanceManager.store(cf = new jmri.jmrix.dcc4pc.swing.Dcc4PcComponentFactory(this), 035 jmri.jmrix.swing.ComponentFactory.class); 036 } 037 038 jmri.jmrix.swing.ComponentFactory cf = null; 039 040 /** 041 * Provides access to the TrafficController for this particular connection. 042 * @return traffic controller. 043 */ 044 public Dcc4PcTrafficController getDcc4PcTrafficController() { 045 return tc; 046 } 047 048 public void setDcc4PcTrafficController(Dcc4PcTrafficController tc) { 049 this.tc = tc; 050 } 051 private Dcc4PcTrafficController tc; 052 053 /** 054 * Configure the common managers for Dcc4Pc connections. This puts the 055 * common manager config in one place. This method is static so that it can 056 * be referenced from classes that don't inherit, including 057 * hexfile.HexFileFrame and locormi.LnMessageClient 058 */ 059 @Override 060 public void configureManagers() { 061 062 InstanceManager.setReporterManager( 063 getReporterManager()); 064 065 InstanceManager.setSensorManager( 066 getSensorManager()); 067 068 register(); 069 } 070 071 public Dcc4PcReporterManager getReporterManager() { 072 if (getDisabled()) { 073 return null; 074 } 075 return (Dcc4PcReporterManager) classObjectMap.computeIfAbsent((ReporterManager.class), (Class<?> c) -> 076 new Dcc4PcReporterManager(getDcc4PcTrafficController(), this)); 077 } 078 079 public Dcc4PcSensorManager getSensorManager() { 080 if (getDisabled()) { 081 return null; 082 } 083 return (Dcc4PcSensorManager) classObjectMap.computeIfAbsent(SensorManager.class, 084 (Class<?> c) -> new Dcc4PcSensorManager(getDcc4PcTrafficController(), this)); 085 } 086 087 @Override 088 protected ResourceBundle getActionModelResourceBundle() { 089 return ResourceBundle.getBundle("jmri.jmrix.dcc4pc.Dcc4PcActionListBundle"); 090 } 091 092 @Override 093 public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) { 094 return new NamedBeanComparator<>(); 095 } 096 097 @Override 098 public void dispose() { 099 tc = null; 100 InstanceManager.deregister(this, Dcc4PcSystemConnectionMemo.class); 101 if (cf != null) { 102 InstanceManager.deregister(cf, jmri.jmrix.swing.ComponentFactory.class); 103 } 104 Dcc4PcSensorManager sm = (Dcc4PcSensorManager) classObjectMap.get(SensorManager.class); 105 if (sm != null) { 106 sm.dispose(); 107 } 108 super.dispose(); 109 } 110 111 /** 112 * Provide Programming on Main through another connection's ops-mode 113 * programmer: it sends the packets, and the readback arrives as RailCom 114 * through this connection. Service mode stays with the other connection. 115 * 116 * @param <T> a manager for both modes 117 * @param dpm the other connection's programmer manager 118 */ 119 public <T extends AddressedProgrammerManager & GlobalProgrammerManager> void setRealProgramManager(T dpm) { 120 provideProgrammer(new Dcc4PcProgrammerManager(dpm, this)); 121 log.info("{} reads CVs on the main through {}", getUserName(), dpm.getUserName()); 122 } 123 124 private void provideProgrammer(Dcc4PcProgrammerManager pm) { 125 store(pm, AddressedProgrammerManager.class); 126 InstanceManager.store(pm, AddressedProgrammerManager.class); 127 } 128 129 /** 130 * {@inheritDoc} 131 * <p> 132 * No consist manager, although this connection provides an ops-mode 133 * programmer: that only forwards to another connection, which provides 134 * its own consists. 135 */ 136 @Override 137 public boolean provides(Class<?> c) { 138 boolean provided = super.provides(c); 139 return provided && !c.equals(ConsistManager.class); 140 } 141 142 /** 143 * Use another connection's ops-mode programmer for Programming on Main 144 * (the connection's "Programmer" option): that connection's command 145 * station sends the packets, and the RailCom reply comes back through 146 * this one. With no connection named, the default Command Station's 147 * connection (Preferences, Defaults) is used. 148 * <p> 149 * This connection offers its ops-mode programmer straight away, so it can 150 * be chosen as the default whichever connection starts first; the other 151 * connection is looked up each time a programmer is needed. 152 * 153 * @param userName the other connection's name, or empty to use the 154 * default command station 155 */ 156 public void useProgrammerFrom(String userName) { 157 boolean useDefault = userName == null || userName.isEmpty(); 158 Supplier<SystemConnectionMemo> other = () -> connectionNamed(useDefault ? defaultCommandStation() : userName); 159 provideProgrammer(new Dcc4PcProgrammerManager( 160 () -> managerOf(other.get(), AddressedProgrammerManager.class), 161 () -> managerOf(other.get(), CommandStation.class), 162 this)); 163 log.info("{} reads CVs on the main through {}", getUserName(), useDefault ? "the default command station" : userName); 164 } 165 166 /** @return the name of the connection set as the default Command Station, or null if none */ 167 private static String defaultCommandStation() { 168 jmri.managers.ManagerDefaultSelector defaults = InstanceManager.getNullableDefault(jmri.managers.ManagerDefaultSelector.class); 169 return defaults == null ? null : defaults.getDefault(CommandStation.class); 170 } 171 172 /** @return the named connection other than this one, or null if it isn't running */ 173 private SystemConnectionMemo connectionNamed(String userName) { 174 if (userName == null) { 175 return null; 176 } 177 SystemConnectionMemo other = SystemConnectionMemoManager.getDefault().getSystemConnectionMemoForUserName(userName); 178 return other == this ? null : other; 179 } 180 181 private static <T> T managerOf(SystemConnectionMemo memo, Class<T> type) { 182 return memo == null ? null : memo.get(type); 183 } 184 185 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Dcc4PcSystemConnectionMemo.class); 186}