001package jmri.managers; 002 003import java.time.LocalDateTime; 004import java.util.Arrays; 005import java.util.LinkedList; 006import java.util.List; 007import javax.annotation.Nonnull; 008 009import jmri.*; 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013/** 014 * Implementation of a TurnoutManager that can serve as a proxy for multiple 015 * system-specific implementations. 016 * 017 * @author Bob Jacobsen Copyright (C) 2003, 2010 018 */ 019public class ProxyTurnoutManager extends AbstractProvidingProxyManager<Turnout> implements TurnoutManager { 020 021 public ProxyTurnoutManager() { 022 super(); 023 } 024 025 @Override 026 protected AbstractManager<Turnout> makeInternalManager() { 027 return jmri.InstanceManager.getDefault(jmri.jmrix.internal.InternalSystemConnectionMemo.class).getTurnoutManager(); 028 } 029 030 /** 031 * {@inheritDoc} 032 */ 033 @Override 034 public void addManager(@Nonnull Manager<Turnout> m) { 035 super.addManager(m); 036 InstanceManager.getDefault(TurnoutOperationManager.class).loadOperationTypes(); 037 } 038 039 /** 040 * Locate via user name, then system name if needed. 041 * 042 * @return Null if nothing by that name exists 043 */ 044 @Override 045 public Turnout getTurnout(@Nonnull String name) { 046 return super.getNamedBean(name); 047 } 048 049 /** 050 * {@inheritDoc} 051 */ 052 @Override 053 @Nonnull 054 protected Turnout makeBean(Manager<Turnout> manager, String systemName, String userName) throws IllegalArgumentException { 055 return ((TurnoutManager) manager).newTurnout(systemName, userName); 056 } 057 058 /** 059 * {@inheritDoc} 060 */ 061 @Override 062 @Nonnull 063 public Turnout provideTurnout(@Nonnull String name) throws IllegalArgumentException { 064 return super.provideNamedBean(name); 065 } 066 067 068 /** {@inheritDoc} */ 069 @Override 070 @Nonnull 071 public Turnout provide(@Nonnull String name) throws IllegalArgumentException { return provideTurnout(name); } 072 073 /** 074 * Get an instance with the specified system and user names. Note that 075 * two calls with the same arguments will get the same instance; there is 076 * only one Sensor object representing a given physical turnout and 077 * therefore only one with a specific system or user name. 078 * <p> 079 * This will always return a valid object reference for a valid request; a 080 * new object will be created if necessary. In that case: 081 * <ul> 082 * <li>If a null reference is given for user name, no user name will be 083 * associated with the Turnout object created; a valid system name must be 084 * provided 085 * <li>If a null reference is given for the system name, a system name will 086 * _somehow_ be inferred from the user name. How this is done is system 087 * specific. Note: a future extension of this interface will add an 088 * exception to signal that this was not possible. 089 * <li>If both names are provided, the system name defines the hardware 090 * access of the desired turnout, and the user address is associated with 091 * it. 092 * </ul> 093 * Note that it is possible to make an inconsistent request if both 094 * addresses are provided, but the given values are associated with 095 * different objects. This is a problem, and we don't have a good solution 096 * except to issue warnings. This will mostly happen if you're creating 097 * Sensors when you should be looking them up. 098 * 099 * @return requested Turnout object (never null) 100 */ 101 @Override 102 @Nonnull 103 public Turnout newTurnout(@Nonnull String systemName, String userName) throws IllegalArgumentException { 104 return newNamedBean(systemName, userName); 105 } 106 107 /** 108 * Get text to be used for the Turnout.CLOSED state in user communication. 109 * Allows text other than "CLOSED" to be use with certain hardware system to 110 * represent the Turnout.CLOSED state. Defaults to the primary manager. This 111 * means that the primary manager sets the terminology used. Note: the 112 * primary manager need not override the method in AbstractTurnoutManager if 113 * "CLOSED" is the desired terminology. 114 */ 115 @Override 116 @Nonnull 117 public String getClosedText() { 118 return ((TurnoutManager) getDefaultManager()).getClosedText(); 119 } 120 121 /** 122 * Get text to be used for the Turnout.THROWN state in user communication. 123 * Allows text other than "THROWN" to be use with certain hardware system to 124 * represent the Turnout.THROWN state. Defaults to the primary manager. This 125 * means that the primary manager sets the terminology used. Note: the 126 * primary manager need not override the method in AbstractTurnoutManager if 127 * "THROWN" is the desired terminology. 128 */ 129 @Override 130 @Nonnull 131 public String getThrownText() { 132 return ((TurnoutManager) getDefaultManager()).getThrownText(); 133 } 134 135 /** 136 * Get from the user, the number of addressed bits used to control a 137 * turnout. Normally this is 1, and the default routine returns 1 138 * automatically. Turnout Managers for systems that can handle multiple 139 * control bits should override this method with one which asks the user to 140 * specify the number of control bits. If the user specifies more than one 141 * control bit, this method should check if the additional bits are 142 * available (not assigned to another object). If the bits are not 143 * available, this method should return 0 for number of control bits, after 144 * informing the user of the problem. 145 */ 146 @Override 147 public int askNumControlBits(@Nonnull String systemName) { 148 return ((TurnoutManager) getManagerOrDefault(systemName)).askNumControlBits(systemName); 149 } 150 151 /** 152 * Get from the user, the type of output to be used bits to control a 153 * turnout. Normally this is 0 for 'steady state' control, and the default 154 * routine returns 0 automatically. Turnout Managers for systems that can 155 * handle pulsed control as well as steady state control should override 156 * this method with one which asks the user to specify the type of control 157 * to be used. The routine should return 0 for 'steady state' control, or n 158 * for 'pulsed' control, where n specifies the duration of the pulse 159 * (normally in seconds). 160 */ 161 @Override 162 public int askControlType(@Nonnull String systemName) { 163 return ((TurnoutManager) getManagerOrDefault(systemName)).askControlType(systemName); 164 } 165 166 /** 167 * {@inheritDoc} 168 */ 169 @Override 170 public boolean isControlTypeSupported(@Nonnull String systemName) { 171 return ((TurnoutManager) getManagerOrDefault(systemName)).isControlTypeSupported(systemName); 172 } 173 174 /** 175 * {@inheritDoc} 176 */ 177 @Override 178 public boolean isNumControlBitsSupported(@Nonnull String systemName) { 179 return ((TurnoutManager) getManagerOrDefault(systemName)).isNumControlBitsSupported(systemName); 180 } 181 182 /** {@inheritDoc} */ 183 @Override 184 @Nonnull 185 public String[] getValidOperationTypes() { 186 List<String> typeList = new LinkedList<>(); 187 getManagerList().forEach(m -> typeList.addAll(Arrays.asList(((TurnoutManager) m).getValidOperationTypes()))); 188 return TurnoutOperationManager.concatenateTypeLists(typeList.toArray(String[]::new)); 189 } 190 191 /** 192 * {@inheritDoc} 193 */ 194 @Override 195 public boolean allowMultipleAdditions(@Nonnull String systemName) { 196 return ((TurnoutManager) getManagerOrDefault(systemName)).allowMultipleAdditions(systemName); 197 } 198 199 /** 200 * {@inheritDoc} 201 */ 202 @Override 203 public void setDefaultClosedSpeed(@Nonnull String speed) throws jmri.JmriException { 204 for (Manager<Turnout> m : getManagerList()) { 205 try { 206 ((TurnoutManager) m).setDefaultClosedSpeed(speed); 207 } catch (jmri.JmriException ex) { 208 log.error("JmriException {}", ex.getMessage() ); 209 throw ex; 210 } 211 } 212 } 213 214 /** 215 * {@inheritDoc} 216 */ 217 @Override 218 public void setDefaultThrownSpeed(@Nonnull String speed) throws jmri.JmriException { 219 for (Manager<Turnout> m : getManagerList()) { 220 try { 221 ((TurnoutManager) m).setDefaultThrownSpeed(speed); 222 } catch (jmri.JmriException ex) { 223 log.error("JmriException {}", ex.getMessage() ); 224 throw ex; 225 } 226 } 227 } 228 229 /** 230 * {@inheritDoc} 231 */ 232 @Override 233 public String getDefaultThrownSpeed() { 234 return ((TurnoutManager) getDefaultManager()).getDefaultThrownSpeed(); 235 } 236 237 /** 238 * {@inheritDoc} 239 */ 240 @Override 241 public String getDefaultClosedSpeed() { 242 return ((TurnoutManager) getDefaultManager()).getDefaultClosedSpeed(); 243 } 244 245 /** {@inheritDoc} 246 * @return outputInterval from default TurnoutManager 247 */ 248 @Override 249 public int getOutputInterval() { 250 return ((TurnoutManager) getDefaultManager()).getOutputInterval(); 251 } 252 253 /** 254 * {@inheritDoc} 255 * This method is only used in jmri.jmrix.internal.InternalTurnoutManagerTest and should not be 256 * used in actual code, as it can overwrite individual per connection values set by the user. 257 */ 258 @Override 259 public void setOutputInterval(int newInterval) { 260 log.debug("setOutputInterval called in ProxyTurnoutManager"); 261 // only intended for testing; do not set interval via ProxyTurnoutManager in actual code 262 for (Manager<Turnout> manager : getManagerList()) { 263 ((TurnoutManager) manager).setOutputInterval(newInterval); 264 } 265 } 266 267 /** 268 * {@inheritDoc} 269 * @return end time of latest OutputInterval as LocalDateTime from default TurnoutManager 270 */ 271 @Nonnull 272 @Override 273 public LocalDateTime outputIntervalEnds() { 274 log.debug("outputIntervalEnds called in ProxyTurnoutManager"); 275 return ((TurnoutManager) getDefaultManager()).outputIntervalEnds(); 276 } 277 278 /** 279 * {@inheritDoc} 280 */ 281 @Override 282 public int getXMLOrder() { 283 return jmri.Manager.TURNOUTS; 284 } 285 286 /** 287 * {@inheritDoc} 288 */ 289 @Override 290 @Nonnull 291 public String getBeanTypeHandled(boolean plural) { 292 return Bundle.getMessage(plural ? "BeanNameTurnouts" : "BeanNameTurnout"); 293 } 294 295 /** 296 * {@inheritDoc} 297 */ 298 @Override 299 public Class<Turnout> getNamedBeanClass() { 300 return Turnout.class; 301 } 302 303 // initialize logging 304 private final static Logger log = LoggerFactory.getLogger(ProxyTurnoutManager.class); 305 306}