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     * @deprecated since 4.15.7; use
038     * #requestThrottle(BasicRosterEntry, ThrottleListener, boolean) instead
039     * 
040     * @param re desired RosterEntry
041     * @param l  ThrottleListener awaiting notification of a found throttle
042     * @return true if the request will continue, false if the request will not
043     *         be made; false may be returned if a the throttle is already in
044     *         use
045     */
046    @Deprecated
047    public boolean requestThrottle(BasicRosterEntry re, ThrottleListener l);
048
049    /**
050     * Request a throttle from a given RosterEntry. When the decoder address is
051     * located, the ThrottleListener gets a callback via the
052     * ThrottleListener.notifyThrottleFound method.
053     *
054     * @param re desired RosterEntry
055     * @param l  ThrottleListener awaiting notification of a found throttle
056     * @param canHandleDecisions true if the ThrottleListener has a mechanism for dealing with
057     *        Share / Steal decisions, else false
058     * @return true if the request will continue, false if the request will not
059     *         be made; false may be returned if a the throttle is already in
060     *         use
061     */
062    public boolean requestThrottle(BasicRosterEntry re, ThrottleListener l, boolean canHandleDecisions);
063
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     *
074     * @param address desired decoder address
075     * @param l       ThrottleListener awaiting notification of a found throttle
076     * @return true if the request will continue, false if the request will not
077     *         be made; false may be returned if a the throttle is already in
078     *         use
079     */
080    public boolean requestThrottle(int address, ThrottleListener l);
081
082    /**
083     * Request a throttle, given a decoder address. When the decoder address is
084     * located, the ThrottleListener gets a callback via the
085     * ThrottleListener.notifyThrottleFound method.
086     * <P>
087     * This is a convenience version of the call, which uses system-specific
088     * logic to tell whether the address is a short or long form,
089     * and assumes that the hardware makes and steal / share decisions.
090     * <p>
091     * @param canHandleDecisions true if the ThrottleListener has a mechanism for dealing with
092     *        Share / Steal decisions, else false
093     * @param address desired decoder address
094     * @param l       ThrottleListener awaiting notification of a found throttle
095     
096     * @return true if the request will continue, false if the request will not
097     *         be made; false may be returned if a the throttle is already in
098     *         use
099     */
100    public boolean requestThrottle(int address, ThrottleListener l, boolean canHandleDecisions);
101
102    /**
103     * Request a throttle, given a decoder address and whether it is a long or
104     * short DCC address. When the decoder address is located, the
105     * ThrottleListener gets a callback via the
106     * ThrottleListener.notifyThrottleFound method.
107     * <p>
108     * @deprecated since 4.15.7; use
109     * #requestThrottle(int, boolean, ThrottleListener, boolean) instead
110     *
111     * @param address desired decoder address
112     * @param isLong  true if requesting a DCC long (extended) address
113     * @param l       ThrottleListener awaiting notification of a found throttle
114     * @return true if the request will continue, false if the request will not
115     *         be made; false may be returned if a the throttle is already in
116     *         use
117     */
118    @Deprecated
119    public boolean requestThrottle(int address, boolean isLong, ThrottleListener l);
120
121    /**
122     * Request a throttle, given a decoder address and whether it is a long or
123     * short DCC address. When the decoder address is located, the
124     * ThrottleListener gets a callback via the
125     * ThrottleListener.notifyThrottleFound method.
126     *
127     * @param address desired decoder address
128     * @param isLong  true if requesting a DCC long (extended) address
129     * @param l       ThrottleListener awaiting notification of a found throttle
130     * @param canHandleDecisions true if the ThrottleListener has a mechanism for dealing with
131     *                Share / Steal decisions, else false
132     * @return true if the request will continue, false if the request will not
133     *         be made; false may be returned if a the throttle is already in
134     *         use
135     */
136    public boolean requestThrottle(int address, boolean isLong, ThrottleListener l, boolean canHandleDecisions);
137
138    /**
139     * Request a throttle, given a decoder address. When the decoder address is
140     * located, the ThrottleListener gets a callback via the
141     * ThrottleListener.notifyThrottleFound method.
142     * <p>
143     * This is a convenience version of the call, which uses system-specific
144     * logic to tell whether the address is a short or long form.
145     *
146     * @deprecated since 4.15.7; use
147     * #requestThrottle(LocoAddress, ThrottleListener, boolean) instead
148     *
149     * @param address desired decoder address
150     * @param l       ThrottleListener awaiting notification of a found throttle
151     * @return true if the request will continue, false if the request will not
152     *         be made; false may be returned if a the throttle is already in
153     *         use
154     */
155    @Deprecated
156    public boolean requestThrottle(LocoAddress address, ThrottleListener l);
157
158    /**
159     * Request a throttle, given a decoder address or a RosterEntry. When the
160     * decoder address is located, the ThrottleListener gets a callback via the
161     * ThrottleListener.notifyThrottleFound method.
162     * <p>
163     * This is a convenience version of the call, which uses system-specific
164     * logic to tell whether the address is a short or long form.
165     * @deprecated since 4.15.7; use
166     * #requestThrottle(LocoAddress, ThrottleListener, boolean) or
167     * #requestThrottle(BasicRosterEntry, ThrottleListener, boolean) instead
168     *
169     * @param address desired decoder address
170     * @param re      desired RosterEntry
171     * @param l       ThrottleListener awaiting notification of a found throttle
172     * @return true if the request will continue, false if the request will not
173     *         be made; false may be returned if a the throttle is already in
174     *         use
175     */
176    @Deprecated
177    public boolean requestThrottle(LocoAddress address, BasicRosterEntry re, ThrottleListener l);
178
179    /**
180     * Request a throttle, given a LocoAddress. When the address is
181     * located, the ThrottleListener gets a callback via the
182     * ThrottleListener.notifyThrottleFound method.
183     *
184     * @param address desired loco address
185     * @param l       ThrottleListener awaiting notification of a found throttle
186     * @param canHandleDecisions true if the ThrottleListener has a mechanism for dealing with
187     *        Share / Steal decisions, else false
188     * @return true if the request will continue, false if the request will not
189     *         be made; false may be returned if a the throttle is already in
190     *         use
191     */
192    public boolean requestThrottle(LocoAddress address, ThrottleListener l, boolean canHandleDecisions);
193    
194    /**
195     * Cancel a request for a throttle.
196     * <P>
197     * This is a convenience version of the call, which uses system-specific
198     * logic to tell whether the address is a short or long form.
199     *
200     * @param re desired Roster Entry
201     * @param l  ThrottleListener canceling the request for a throttle
202     */
203    public void cancelThrottleRequest(BasicRosterEntry re, ThrottleListener l);
204    
205    /**
206     * Cancel a request for a throttle.
207     * <P>
208     * This is a convenience version of the call, which uses system-specific
209     * logic to tell whether the address is a short or long form.
210     *
211     * @param address desired decoder address
212     * @param l       ThrottleListener canceling request for a throttle
213     */
214    public void cancelThrottleRequest(int address, ThrottleListener l);
215    
216    /**
217     * Cancel a request for a throttle.
218     *
219     * @param address desired decoder address
220     * @param isLong  true if requesting a DCC long (extended) address
221     * @param l       ThrottleListener canceling request for a throttle
222     */
223    public void cancelThrottleRequest(int address, boolean isLong, ThrottleListener l);
224
225    
226    /**
227     * Cancel a request for a throttle.
228     *
229     * @param address unwanted Loco address
230     * @param l       ThrottleListener canceling request for a throttle
231     */
232    public void cancelThrottleRequest(LocoAddress address, ThrottleListener l);
233
234    /**
235     * Steal a requested throttle.
236     * <p>
237     * This is a convenience version of the call, which uses system-specific
238     * logic to tell whether the address is a short or long form.
239     *
240     * @param re desired Roster Entry
241     * @param l  ThrottleListener requesting the throttle steal occur.
242     * @param steal true if the request should continue, false otherwise.
243     * @since 4.9.2
244     */
245    @Deprecated
246    public void stealThrottleRequest(BasicRosterEntry re, ThrottleListener l,boolean steal);
247
248    /**
249     * Steal a requested throttle.
250     * <p>
251     * This is a convenience version of the call, which uses system-specific
252     * logic to tell whether the address is a short or long form.
253     *
254     * @param address desired decoder address
255     * @param l  ThrottleListener requesting the throttle steal occur.
256     * @param steal true if the request should continue, false otherwise.
257     * @since 4.9.2
258     * 
259     * @deprecated since 4.15.7; use #responseThrottleDecision
260     */
261    @Deprecated
262    public void stealThrottleRequest(LocoAddress address, ThrottleListener l, boolean steal);
263    
264    
265    /**
266     * Steal a requested throttle.
267     * <P>
268     * This is a convenience version of the call, which uses system-specific
269     * logic to tell whether the address is a short or long form.
270     *
271     * @deprecated since 4.15.7; use #responseThrottleDecision
272     *
273     * @param address desired decoder address
274     * @param l  ThrottleListener requesting the throttle steal occur.
275     * @param steal true if the request should continue, false otherwise.
276     * @since 4.9.2
277     */
278    @Deprecated
279    public void stealThrottleRequest(int address, ThrottleListener l,boolean steal);
280    
281    /**
282     * Steal a requested throttle.
283     * <P>
284     * This is a convenience version of the call, which uses system-specific
285     * logic to tell whether the address is a short or long form.
286     *
287     * @deprecated since 4.15.7; use #responseThrottleDecision
288     *
289     * @param address desired decoder address
290     * @param isLong  true if requesting a DCC long (extended) address
291     * @param l  ThrottleListener requesting the throttle steal occur.
292     * @param steal true if the request should continue, false otherwise.
293     * @since 4.9.2
294     */
295    @Deprecated
296    public void stealThrottleRequest(int address, boolean isLong, ThrottleListener l,boolean steal);
297    
298    /**
299     * Steal or Share a requested throttle.
300     * <P>
301     * This is a convenience version of the call, which uses system-specific
302     * logic to tell whether the address is a short or long form.
303     *
304     * @param address desired decoder address
305     * @param l  ThrottleListener requesting the throttle steal occur.
306     * @param decision from the ThrottleListener, STEAL or SHARE.
307     */
308    public void responseThrottleDecision(int address, ThrottleListener l, ThrottleListener.DecisionType decision);
309    
310    /**
311     * Steal or Share a requested throttle.
312     * <P>
313     * This is a convenience version of the call, which uses system-specific
314     * logic to tell whether the address is a short or long form.
315     *
316     * @param address desired decoder address
317     * @param isLong  true if requesting a DCC long (extended) address
318     * @param l  ThrottleListener requesting the throttle steal occur.
319     * @param decision from the ThrottleListener, STEAL or SHARE.
320     */
321    public void responseThrottleDecision(int address, boolean isLong, ThrottleListener l, ThrottleListener.DecisionType decision);
322    
323    /**
324     * Steal or Share a requested throttle.
325     *
326     * @param address desired LocoAddress
327     * @param l The ThrottleListener which has made the decision
328     * @param decision from the ThrottleListener, STEAL or SHARE.
329     * @since 4.9.2
330     */
331    public void responseThrottleDecision(LocoAddress address, ThrottleListener l, ThrottleListener.DecisionType decision);
332    
333    /**
334     * Test if the Silent Steal Throttles preference option should be enabled.
335     *
336     * @return true if steal is possible; false otherwise
337     */
338    public boolean enablePrefSilentStealOption();
339    
340    /**
341     * Test if the Silent Share Throttles preference option should be enabled.
342     *
343     * @return true if steal is possible; false otherwise
344     */
345    public boolean enablePrefSilentShareOption();
346    
347    /**
348     * Test if the Dispatch Button should be enabled or not.
349     *
350     * @return true if dispatch is possible; false otherwise
351     */
352    public boolean hasDispatchFunction();
353
354    /**
355     * Test if a specific number is a valid long address on this system.
356     *
357     * @param address address number to test
358     * @return true if address can be long; false otherwise
359     */
360    public boolean canBeLongAddress(int address);
361
362    /**
363     * Test if a specific number is a valid short address on this system.
364     *
365     * @param address address number to test
366     * @return true if address can be short; false otherwise
367     */
368    public boolean canBeShortAddress(int address);
369
370    /**
371     * Test if ambiguous addresses (short vs long) are not allowed on this
372     * system. Also indicates support for multi-protocol decoders.
373     *
374     * @return true if ambiguous addresses are not allowed; false otherwise
375     */
376    public boolean addressTypeUnique();
377
378    /**
379     * This returns a list of the different protocols that are supported by the
380     * system, to include short vs long or DCC vs Selectrix vs Motorola.
381     *
382     * @return the list of supported address protocols
383     */
384    public String[] getAddressTypes();
385
386    /**
387     * Get a string value for a given protocol value.
388     *
389     * @param prot the protocol
390     * @return a human-readable, possibly localized, description of the protocol
391     */
392    public String getAddressTypeString(LocoAddress.Protocol prot);
393
394    /**
395     * Get a list of different protocols supported by the system, to include
396     * short vs long or DCC vs Selectrix vs Motorola.
397     *
398     * @return a list of supported address protocols
399     */
400    public LocoAddress.Protocol[] getAddressProtocolTypes();
401
402    /**
403     * Get a protocol given a description.
404     *
405     * @param selection human-readable, possibly localized, description of the
406     *                  protocol
407     * @return the protocol
408     */
409    public LocoAddress.Protocol getProtocolFromString(String selection);
410
411    /**
412     * Get the object representing a particular address.
413     *
414     * @param value    address in protocol-specific format
415     * @param protocol specific protocol string, see the specific throttle
416     *                 manager for values
417     * @return the address, possibly as a protocol-specific subclass
418     */
419    public LocoAddress getAddress(String value, String protocol);
420
421    /**
422     * Get the object representing a particular address.
423     *
424     * @param value    address in protocol-specific format
425     * @param protocol the control protocol
426     * @return the address, possibly as a protocol-specific subclass
427     */
428    public LocoAddress getAddress(String value, LocoAddress.Protocol protocol);
429
430    /**
431     * Get the supported speed modes.
432     *
433     * @return an XOR of the possible modes specified in the throttle interface
434     */
435    public EnumSet<SpeedStepMode> supportedSpeedModes();
436
437    /**
438     * Provides a Proxy method to return the SpeedSetting, Direction, Function
439     * Settings, of a throttle, where the requesting code has used
440     * {@link #attachListener(LocoAddress, java.beans.PropertyChangeListener) attachListener}
441     * to only be notified of changes in the throttle and not control it.
442     * <p>
443     * Valid values for item are IsForward SpeedSetting SpeedIncrement
444     * SpeedStepMode F0-F28
445     *
446 * @param la   LocoAddress that we wish interrogate
447     * @param item A string of the item we wish to know the value of.
448     * @return the value as an object, if the loco address has not been assigned
449     *         to a throttle or the item value is not valid, null is returned.
450     */
451    public Object getThrottleInfo(LocoAddress la, String item);
452
453    /**
454     * 
455     * @param la Loco address to test
456     * @return true, its still required, false its not.
457     */
458    public boolean addressStillRequired(LocoAddress la);
459
460    /**
461     * 
462     * @param address Loco number to test.
463     * @param addressIsLong true if long address.
464     * @return true, its still required, false its not.
465     */
466    public boolean addressStillRequired(int address, boolean addressIsLong);
467    
468    /**
469     * 
470     * @param address Loco number to test
471     * @return true, its still required, false its not.
472     */
473    public boolean addressStillRequired(int address);
474
475    /**
476     * 
477     * @param re roster entry to test
478     * @return true, its still required, false its not.
479     */
480    public boolean addressStillRequired(BasicRosterEntry re);
481    
482    /**
483     * The specified Throttle Listener has finished using a given throttle and
484     * no longer requires access to it.
485     * <p>
486     * After releasing the throttle, the manager will perform further checks to
487     * see if it is in use by any other listeners or if there are any
488     * PropertyChangeListeners attached. If there are no other uses of the
489     * throttle then it is disposed of.
490     * <p>
491     * Normally, release ends with a call to dispose.
492     *
493     * @param t Throttle being released
494     * @param l Throttle Listener releasing the throttle
495     */
496    public void releaseThrottle(DccThrottle t, ThrottleListener l);
497
498    /**
499     * Not for general use, see
500     * {@link #releaseThrottle(DccThrottle, ThrottleListener) releaseThrottle}
501     * and
502     * {@link #dispatchThrottle(DccThrottle, ThrottleListener) dispatchThrottle}.
503     * <p>
504     * Dispose of object when finished it. This will free up hardware resource
505     * <p>
506     * Used for handling certain internal error conditions, where the object
507     * still exists but hardware is not associated with it.
508     * <p>
509     * After this, further usage of this Throttle object will result in a
510     * JmriException.
511     *
512     * @param t Throttle being released
513     * @param l Throttle Listener releasing the throttle
514     * @return true if the throttle has been disposed of.
515     */
516    public boolean disposeThrottle(DccThrottle t, ThrottleListener l);
517
518    /**
519     * The throttle listener has finished with the specific Throttle and is is
520     * available for reuse/reallocation by somebody else. If possible, tell the
521     * layout that this locomotive has been dispatched to another user. Not all
522     * layouts will implement this, in which case it is synomous with release();
523     * <p>
524     * Normally, dispatch ends with a call to dispose.
525     *
526     * @param t Throttle being released
527     * @param l Throttle Listener releasing the throttle
528     */
529    public void dispatchThrottle(DccThrottle t, ThrottleListener l);
530
531    /**
532     * Attach a PropertyChangeListener to a specific loco address, where the
533     * requesting code does not need or require control over the loco. If the
534     * loco address is not in the active in the list, then a new throttle will
535     * be created by the manager and the listener attached.
536     * <p>
537     * The PropertyChangeListener will be notified if it has been attached to a
538     * loco address or not, via a PropertyChange notification.
539     * <p>
540     * @param la LocoAddress of the loco we wish to monitor
541     * @param p  PropertyChangeListener to attach to the throttle
542     */
543    public void attachListener(LocoAddress la, PropertyChangeListener p);
544
545    /**
546     * Remove a PropertyChangeListener to a specific loco address, where the
547     * requesting code has used
548     * {@link #attachListener(LocoAddress, java.beans.PropertyChangeListener) attachListener}
549     * to get notification of changes in a throttle.
550     * <p>
551     * The PropertyChangeListener will be notified if it has been removed via a
552     * PropertyChange notification.
553     *
554     * @param la LocoAddress of the loco we wish to monitor
555     * @param p  PropertyChangeListener to remove from the throttle
556     */
557    public void removeListener(LocoAddress la, PropertyChangeListener p);
558
559    /**
560     * Get the user name of the system that the programmer is associated with.
561     *
562     * @return the user name for the system
563     */
564    public String getUserName();
565
566    /**
567     * Get the number of Throttles sharing the throttle for a ddcaddress.
568     *
569     * @param la LocoAddress of the loco you want the throttle usage count for.
570     * @return number of throttles for this address, or 0 if throttle does not exist
571     */
572    public int getThrottleUsageCount(LocoAddress la);
573    
574     /**
575     * Get the number of Throttles sharing the throttle for a ddcaddress.
576     *
577     * @param address number of the loco you want the throttle usage count for.
578     * @param isLongAddress indicates whether the address is long or not.
579     * @return number of throttles for this address, or 0 if throttle does not exist
580     */
581     public int getThrottleUsageCount(int address, boolean isLongAddress);
582
583    /**
584     * Get the number of Throttles sharing the throttle for a ddcaddress.
585     *
586     * @param address number of the loco you want the throttle usage count for.
587     * @return number of throttles for this address, or 0 if throttle does not exist
588     */
589    public int getThrottleUsageCount(int address);
590
591    /**
592     * Get the number of Throttles sharing the throttle for a ddcaddress.
593     *
594     * @param re BasicRosterEntry of the loco you want the throttle usage count for.
595     * @return number of throttles for this address, or 0 if throttle does not exist
596     */
597    public int getThrottleUsageCount(BasicRosterEntry re);
598
599
600}