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