001package jmri; 002 003import java.beans.PropertyChangeListener; 004import java.util.EnumSet; 005 006/** 007 * Interface for allocating {@link Throttle} objects. 008 * <p> 009 * "Address" is interpreted in the context of the DCC implementation. Different 010 * systems will distinguish between short and long addresses in different ways. 011 * <p> 012 * When the allocated Throttle is no longer needed, it is told that it's 013 * released. If a specific ThrottleManager and/or Throttle implementation needs 014 * to keep track of that operation, it is handled internally. 015 * 016 * <hr> 017 * This file is part of JMRI. 018 * <p> 019 * JMRI is free software; you can redistribute it and/or modify it under the 020 * terms of version 2 of the GNU General Public License as published by the Free 021 * Software Foundation. See the "COPYING" file for a copy of this license. 022 * <p> 023 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 024 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 025 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 026 * 027 * @author Glen Oberhauser 028 * @author Bob Jacobsen Copyright 2006 029 */ 030public interface ThrottleManager { 031 032 /** 033 * Request a throttle from a given RosterEntry. When the decoder address is 034 * located, the ThrottleListener gets a callback via the 035 * ThrottleListener.notifyThrottleFound method. 036 * 037 * @param re desired RosterEntry 038 * @param l ThrottleListener awaiting notification of a found throttle 039 * @param canHandleDecisions true if the ThrottleListener has a mechanism for dealing with 040 * Share / Steal decisions, else false 041 * @return true if the request will continue, false if the request will not 042 * be made; false may be returned if a the throttle is already in 043 * use 044 */ 045 boolean requestThrottle(BasicRosterEntry re, ThrottleListener l, boolean canHandleDecisions); 046 047 048 /** 049 * Request a throttle, given a decoder address. When the decoder address is 050 * located, the ThrottleListener gets a callback via the 051 * ThrottleListener.notifyThrottleFound method. 052 * <p> 053 * This is a convenience version of the call, which uses system-specific 054 * logic to tell whether the address is a short or long form, 055 * and assumes that the hardware makes and steal / share decisions. 056 * 057 * @param address desired decoder address 058 * @param l ThrottleListener awaiting notification of a found throttle 059 * @return true if the request will continue, false if the request will not 060 * be made; false may be returned if a the throttle is already in 061 * use 062 */ 063 boolean requestThrottle(int address, ThrottleListener l); 064 065 /** 066 * Request a throttle, given a decoder address. When the decoder address is 067 * located, the ThrottleListener gets a callback via the 068 * ThrottleListener.notifyThrottleFound method. 069 * <p> 070 * This is a convenience version of the call, which uses system-specific 071 * logic to tell whether the address is a short or long form, 072 * and assumes that the hardware makes and steal / share decisions. 073 * @param canHandleDecisions true if the ThrottleListener has a mechanism for dealing with 074 * Share / Steal decisions, else false 075 * @param address desired decoder address 076 * @param l ThrottleListener awaiting notification of a found throttle 077 078 * @return true if the request will continue, false if the request will not 079 * be made; false may be returned if a the throttle is already in 080 * use 081 */ 082 boolean requestThrottle(int address, ThrottleListener l, boolean canHandleDecisions); 083 084 /** 085 * Request a throttle, given a decoder address and whether it is a long or 086 * short DCC address. When the decoder address is located, the 087 * ThrottleListener gets a callback via the 088 * ThrottleListener.notifyThrottleFound method. 089 * 090 * @param address desired decoder address 091 * @param isLong true if requesting a DCC long (extended) address 092 * @param l ThrottleListener awaiting notification of a found throttle 093 * @param canHandleDecisions true if the ThrottleListener has a mechanism for dealing with 094 * Share / Steal decisions, else false 095 * @return true if the request will continue, false if the request will not 096 * be made; false may be returned if a the throttle is already in 097 * use 098 */ 099 boolean requestThrottle(int address, boolean isLong, ThrottleListener l, boolean canHandleDecisions); 100 101 /** 102 * Request a throttle, given a LocoAddress. When the address is 103 * located, the ThrottleListener gets a callback via the 104 * ThrottleListener.notifyThrottleFound method. 105 * 106 * @param address desired loco address 107 * @param l ThrottleListener awaiting notification of a found throttle 108 * @param canHandleDecisions true if the ThrottleListener has a mechanism for dealing with 109 * Share / Steal decisions, else false 110 * @return true if the request will continue, false if the request will not 111 * be made; false may be returned if a the throttle is already in 112 * use 113 */ 114 boolean requestThrottle(LocoAddress address, ThrottleListener l, boolean canHandleDecisions); 115 116 /** 117 * Cancel a request for a throttle. 118 * <p> 119 * This is a convenience version of the call, which uses system-specific 120 * logic to tell whether the address is a short or long form. 121 * 122 * @param re desired Roster Entry 123 * @param l ThrottleListener canceling the request for a throttle 124 */ 125 void cancelThrottleRequest(BasicRosterEntry re, ThrottleListener l); 126 127 /** 128 * Cancel a request for a throttle. 129 * <p> 130 * This is a convenience version of the call, which uses system-specific 131 * logic to tell whether the address is a short or long form. 132 * 133 * @param address desired decoder address 134 * @param l ThrottleListener canceling request for a throttle 135 */ 136 void cancelThrottleRequest(int address, ThrottleListener l); 137 138 /** 139 * Cancel a request for a throttle. 140 * 141 * @param address desired decoder address 142 * @param isLong true if requesting a DCC long (extended) address 143 * @param l ThrottleListener canceling request for a throttle 144 */ 145 void cancelThrottleRequest(int address, boolean isLong, ThrottleListener l); 146 147 /** 148 * Cancel a request for a throttle. 149 * 150 * @param address unwanted Loco address 151 * @param l ThrottleListener canceling request for a throttle 152 */ 153 void cancelThrottleRequest(LocoAddress address, ThrottleListener l); 154 155 /** 156 * Steal or Share a requested throttle. 157 * <p> 158 * This is a convenience version of the call, which uses system-specific 159 * logic to tell whether the address is a short or long form. 160 * 161 * @param address desired decoder address 162 * @param l ThrottleListener requesting the throttle steal occur. 163 * @param decision from the ThrottleListener, STEAL or SHARE. 164 */ 165 void responseThrottleDecision(int address, ThrottleListener l, ThrottleListener.DecisionType decision); 166 167 /** 168 * Steal or Share a requested throttle. 169 * <p> 170 * This is a convenience version of the call, which uses system-specific 171 * logic to tell whether the address is a short or long form. 172 * 173 * @param address desired decoder address 174 * @param isLong true if requesting a DCC long (extended) address 175 * @param l ThrottleListener requesting the throttle steal occur. 176 * @param decision from the ThrottleListener, STEAL or SHARE. 177 */ 178 void responseThrottleDecision(int address, boolean isLong, ThrottleListener l, ThrottleListener.DecisionType decision); 179 180 /** 181 * Steal or Share a requested throttle. 182 * 183 * @param address desired LocoAddress 184 * @param l The ThrottleListener which has made the decision 185 * @param decision from the ThrottleListener, STEAL or SHARE. 186 * @since 4.9.2 187 */ 188 void responseThrottleDecision(LocoAddress address, ThrottleListener l, ThrottleListener.DecisionType decision); 189 190 /** 191 * Test if the Silent Steal Throttles preference option should be enabled. 192 * 193 * @return true if steal is possible; false otherwise 194 */ 195 boolean enablePrefSilentStealOption(); 196 197 /** 198 * Test if the Silent Share Throttles preference option should be enabled. 199 * 200 * @return true if steal is possible; false otherwise 201 */ 202 boolean enablePrefSilentShareOption(); 203 204 /** 205 * Test if the Dispatch Button should be enabled or not. 206 * 207 * @return true if dispatch is possible; false otherwise 208 */ 209 boolean hasDispatchFunction(); 210 211 /** 212 * Test if a specific number is a valid long address on this system. 213 * 214 * @param address address number to test 215 * @return true if address can be long; false otherwise 216 */ 217 boolean canBeLongAddress(int address); 218 219 /** 220 * Test if a specific number is a valid short address on this system. 221 * 222 * @param address address number to test 223 * @return true if address can be short; false otherwise 224 */ 225 boolean canBeShortAddress(int address); 226 227 /** 228 * Test if ambiguous addresses (short vs long) are not allowed on this 229 * system. Also indicates support for multi-protocol decoders. 230 * 231 * @return true if ambiguous addresses are not allowed; false otherwise 232 */ 233 boolean addressTypeUnique(); 234 235 /** 236 * This returns a list of the different protocols that are supported by the 237 * system, to include short vs long or DCC vs Selectrix vs Motorola. 238 * 239 * @return the list of supported address protocols 240 */ 241 String[] getAddressTypes(); 242 243 /** 244 * Get a string value for a given protocol value. 245 * 246 * @param prot the protocol 247 * @return a human-readable, possibly localized, description of the protocol 248 */ 249 String getAddressTypeString(LocoAddress.Protocol prot); 250 251 /** 252 * Get a list of different protocols supported by the system, to include 253 * short vs long or DCC vs Selectrix vs Motorola. 254 * 255 * @return a list of supported address protocols 256 */ 257 LocoAddress.Protocol[] getAddressProtocolTypes(); 258 259 /** 260 * Get a protocol given a description. 261 * 262 * @param selection human-readable, possibly localized, description of the 263 * protocol 264 * @return the protocol 265 */ 266 LocoAddress.Protocol getProtocolFromString(String selection); 267 268 /** 269 * Get the object representing a particular address. 270 * 271 * @param value address in protocol-specific format 272 * @param protocol specific protocol string, see the specific throttle 273 * manager for values 274 * @return the address, possibly as a protocol-specific subclass 275 */ 276 LocoAddress getAddress(String value, String protocol); 277 278 /** 279 * Get the object representing a particular address. 280 * 281 * @param value address in protocol-specific format 282 * @param protocol the control protocol 283 * @return the address, possibly as a protocol-specific subclass 284 */ 285 LocoAddress getAddress(String value, LocoAddress.Protocol protocol); 286 287 /** 288 * Get the supported speed modes. 289 * 290 * @return an XOR of the possible modes specified in the throttle interface 291 */ 292 EnumSet<SpeedStepMode> supportedSpeedModes(); 293 294 /** 295 * Provides a Proxy method to return the SpeedSetting, Direction, Function 296 * Settings, of a throttle, where the requesting code has used 297 * {@link #attachListener(LocoAddress, java.beans.PropertyChangeListener) attachListener} 298 * to only be notified of changes in the throttle and not control it. 299 * <p> 300 * Valid values for item are IsForward SpeedSetting SpeedIncrement 301 * SpeedStepMode F0-F28 302 * 303 * @param la LocoAddress that we wish interrogate 304 * @param item A string of the item we wish to know the value of. 305 * @return the value as an object, if the loco address has not been assigned 306 * to a throttle or the item value is not valid, null is returned. 307 */ 308 Object getThrottleInfo(LocoAddress la, String item); 309 310 /** 311 * 312 * @param la Loco address to test 313 * @return true, its still required, false its not. 314 */ 315 boolean addressStillRequired(LocoAddress la); 316 317 /** 318 * 319 * @param address Loco number to test. 320 * @param addressIsLong true if long address. 321 * @return true, its still required, false its not. 322 */ 323 boolean addressStillRequired(int address, boolean addressIsLong); 324 325 /** 326 * 327 * @param address Loco number to test 328 * @return true, its still required, false its not. 329 */ 330 boolean addressStillRequired(int address); 331 332 /** 333 * 334 * @param re roster entry to test 335 * @return true, its still required, false its not. 336 */ 337 boolean addressStillRequired(BasicRosterEntry re); 338 339 /** 340 * The specified Throttle Listener has finished using a given throttle and 341 * no longer requires access to it. 342 * <p> 343 * After releasing the throttle, the manager will perform further checks to 344 * see if it is in use by any other listeners or if there are any 345 * PropertyChangeListeners attached. If there are no other uses of the 346 * throttle then it is disposed of. 347 * <p> 348 * Normally, release ends with a call to dispose. 349 * 350 * @param t Throttle being released 351 * @param l Throttle Listener releasing the throttle 352 */ 353 void releaseThrottle(DccThrottle t, ThrottleListener l); 354 355 /** 356 * Not for general use, see 357 * {@link #releaseThrottle(DccThrottle, ThrottleListener) releaseThrottle} 358 * and 359 * {@link #dispatchThrottle(DccThrottle, ThrottleListener) dispatchThrottle}. 360 * <p> 361 * Dispose of object when finished it. This will free up hardware resource 362 * <p> 363 * Used for handling certain internal error conditions, where the object 364 * still exists but hardware is not associated with it. 365 * <p> 366 * After this, further usage of this Throttle object will result in a 367 * JmriException. 368 * 369 * @param t Throttle being released 370 * @param l Throttle Listener releasing the throttle 371 * @return true if the throttle has been disposed of. 372 */ 373 boolean disposeThrottle(DccThrottle t, ThrottleListener l); 374 375 /** 376 * The throttle listener has finished with the specific Throttle and is is 377 * available for reuse/reallocation by somebody else. If possible, tell the 378 * layout that this locomotive has been dispatched to another user. Not all 379 * layouts will implement this, in which case it is synomous with release(); 380 * <p> 381 * Normally, dispatch ends with a call to dispose. 382 * 383 * @param t Throttle being released 384 * @param l Throttle Listener releasing the throttle 385 */ 386 void dispatchThrottle(DccThrottle t, ThrottleListener l); 387 388 /** 389 * Attach a PropertyChangeListener to a specific loco address, where the 390 * requesting code does not need or require control over the loco. If the 391 * loco address is not in the active in the list, then a new throttle will 392 * be created by the manager and the listener attached. 393 * <p> 394 * The PropertyChangeListener will be notified if it has been attached to a 395 * loco address or not, via a PropertyChange notification. 396 * 397 * @param la LocoAddress of the loco we wish to monitor 398 * @param p PropertyChangeListener to attach to the throttle 399 */ 400 void attachListener(LocoAddress la, PropertyChangeListener p); 401 402 /** 403 * Remove a PropertyChangeListener to a specific loco address, where the 404 * requesting code has used 405 * {@link #attachListener(LocoAddress, java.beans.PropertyChangeListener) attachListener} 406 * to get notification of changes in a throttle. 407 * <p> 408 * The PropertyChangeListener will be notified if it has been removed via a 409 * PropertyChange notification. 410 * 411 * @param la LocoAddress of the loco we wish to monitor 412 * @param p PropertyChangeListener to remove from the throttle 413 */ 414 void removeListener(LocoAddress la, PropertyChangeListener p); 415 416 /** 417 * Get the user name of the system that the programmer is associated with. 418 * 419 * @return the user name for the system 420 */ 421 String getUserName(); 422 423 /** 424 * Get the number of Throttles sharing the throttle for a ddcaddress. 425 * 426 * @param la LocoAddress of the loco you want the throttle usage count for. 427 * @return number of throttles for this address, or 0 if throttle does not exist 428 */ 429 int getThrottleUsageCount(LocoAddress la); 430 431 /** 432 * Get the number of Throttles sharing the throttle for a ddcaddress. 433 * 434 * @param address number of the loco you want the throttle usage count for. 435 * @param isLongAddress indicates whether the address is long or not. 436 * @return number of throttles for this address, or 0 if throttle does not exist 437 */ 438 int getThrottleUsageCount(int address, boolean isLongAddress); 439 440 /** 441 * Get the number of Throttles sharing the throttle for a ddcaddress. 442 * 443 * @param address number of the loco you want the throttle usage count for. 444 * @return number of throttles for this address, or 0 if throttle does not exist 445 */ 446 int getThrottleUsageCount(int address); 447 448 /** 449 * Get the number of Throttles sharing the throttle for a ddcaddress. 450 * 451 * @param re BasicRosterEntry of the loco you want the throttle usage count for. 452 * @return number of throttles for this address, or 0 if throttle does not exist 453 */ 454 int getThrottleUsageCount(BasicRosterEntry re); 455 456 /** 457 * Allow to cleanly release the traffic controller in ThrottleManager Tests 458 * <ul> 459 * <li>remove listeners, if any</li> 460 * <li>stop timers, is any</li> 461 * </ul> 462 */ 463 void dispose(); 464 465}