001package jmri;
002
003import java.util.Hashtable;
004import java.util.LinkedHashMap;
005import java.util.List;
006import javax.annotation.CheckForNull;
007import javax.annotation.Nonnull;
008import jmri.jmrit.display.layoutEditor.LayoutBlock;
009import jmri.jmrit.display.layoutEditor.LevelXing;
010
011/**
012 * Generic interface for Signal Mast Logic. Signal Mast Logic allows to build up
013 * a set of criteria for a Signal Mast as to what Aspect it should be displaying
014 * for a specific route through to a destination Signal Mast.
015 *
016 *  * @see jmri.implementation.DefaultSignalMastLogic
017 *
018 * @author Kevin Dickerson Copyright (C) 2011
019 */
020public interface SignalMastLogic extends NamedBean {
021
022    /**
023     * Constant representing that all the user entered details relating to a
024     * signal mast logic are stored. Automatically generated details that have
025     * been entered via the setAutoBean are not stored.
026     */
027    int STOREALL = 0;
028    
029    /**
030     * Constant representing that only the basic Signal Mast Logic details are
031     * stored. All details that determine the triggering of the logic are not
032     * stored.
033     */
034    int STOREMASTSONLY = 2;
035    
036    /**
037     * Constant representing that this Signal Mast Logic is not stored with the
038     * panel file. This is used where another piece of code uses handles the
039     * dynamic creation of signalmast logic
040     */
041    int STORENONE = 4;
042
043    /**
044     * String constant for sensors.
045     */
046    String PROPERTY_SENSORS = "sensors";
047
048    /**
049     * String constant for turnouts.
050     */
051    String PROPERTY_TURNOUTS = "turnouts";
052
053    /**
054     * String constant for auto turnouts.
055     */
056    String PROPERTY_AUTO_TURNOUTS = "autoturnouts";
057
058    /**
059     * String constant for blocks.
060     */
061    String PROPERTY_BLOCKS = "blocks";
062
063    /**
064     * String constant for auto blocks.
065     */
066    String PROPERTY_AUTO_BLOCKS = "autoblocks";
067
068    /**
069     * String constant for masts.
070     */
071    String PROPERTY_MASTS = "masts";
072
073    /**
074     * String constant for auto masts.
075     */
076    String PROPERTY_AUTO_MASTS = "automasts";
077
078    /**
079     * String constant for updated source.
080     */
081    String PROPERTY_UPDATED_SOURCE = "updatedSource";
082
083    /**
084     * String constant for updated destination.
085     */
086    String PROPERTY_UPDATED_DESTINATION = "updatedDestination";
087
088    /**
089     * String constant for length.
090     */
091    String PROPERTY_LENGTH = "length";
092
093    /**
094     * Query if we are allowing the system to automatically generate a list of
095     * conflicting Signal Mast that have a direct effect on our logic.
096     *
097     * @param destination controlled signal mast
098     * @return true if this is allowed.
099     */
100    boolean allowAutoMaticSignalMastGeneration(SignalMast destination);
101
102    /**
103     * Sets whether we should allow the system to automatically generate a list
104     * of signal masts that could cause a conflicting route.
105     *
106     * @param allow       set true if we are to allow automatic generation.
107     * @param destination controlled signal mast
108     */
109    void allowAutoMaticSignalMastGeneration(boolean allow, SignalMast destination);
110
111    /**
112     * Sets whether we should lock all turnouts between the source and
113     * destination signal masts when the logic goes active, to prevent them from
114     * being changed. This is dependant upon the hardware allowing for this.
115     *
116     * @param lock        set true if the system should lock the turnout.
117     * @param destination controlled signal mast
118     */
119    void allowTurnoutLock(boolean lock, SignalMast destination);
120
121    /**
122     * Returns true if any of the blocks in the supplied list are included in
123     * any of the logics that set this signal.
124     *
125     * @param blks A list of Layout Blocks to query against
126     * @return whether all supplied blocks are in at least one of the logics
127     */
128    boolean areBlocksIncluded(List<Block> blks);
129
130    /**
131     * Replace the existing source Signal Mast with another signal mast. This is
132     * for use with such tools as the Layout Editor where a signal mast in a
133     * certain location can be replaced with another, while the remainder of the
134     * configuration stays the same.
135     *
136     * @param oldMast Signal Mast currently configured as the source mast
137     * @param newMast Signal Mast to act as the replacement source mast
138     */
139    void replaceSourceMast(SignalMast oldMast, SignalMast newMast);
140
141    /**
142     * Replace the existing destination Signal Mast with another signal mast.
143     * This is for use with such tools as the Layout Editor where a signalmast
144     * in a certain location can be replaced with another, while the remainder
145     * of the configuration stays the same.
146     *
147     * @param oldMast Signal Mast currently configured as the destination mast
148     * @param newMast Signal Mast to act as the replacement destination mast
149     */
150    void replaceDestinationMast(SignalMast oldMast, SignalMast newMast);
151
152    /**
153     * Remove references to and from this object, so that it can eventually be
154     * garbage-collected.
155     */
156    @Override
157    void dispose();
158
159    /**
160     * Return the Section configured between the source and destination mast.
161     *
162     * @param destination controlled signal mast
163     * @return The section object
164     */
165    Section getAssociatedSection(SignalMast destination);
166
167    /**
168     * Define a Section between the source and destination mast.
169     *
170     * @param sec         The section
171     * @param destination controlled signal mast
172     */
173    void setAssociatedSection(Section sec, SignalMast destination);
174
175    /**
176     * Return the Set State of a control block as it is configured between the
177     * source and destination mast.
178     *
179     * @param block       The Control Layout Block.
180     * @param destination controlled signal mast
181     * @return The int value representing the occupancy state that the block
182     *         should show
183     */
184    int getAutoBlockState(Block block, SignalMast destination);
185
186    /**
187     * Return all the blocks that have been detected as being in use for this
188     * logic. This includes blocks on level xings that are not directly in the
189     * path but do have an effect on the logic.
190     *
191     * @param destination controlled signal mast
192     * @return A list of Block objects
193     */
194    List<Block> getAutoBlocks(SignalMast destination);
195
196    /**
197     * Return a list of blocks just that have been detected as being directly
198     * between the source and destination mast. The order of the blocks in the
199     * list is the order in which they are connected.
200     *
201     * @param destination controlled signal mast
202     * @return A list of block objects
203     */
204    @Nonnull
205    List<Block> getAutoBlocksBetweenMasts(SignalMast destination);
206
207    /**
208     * Return a list of control masts that have been automatically detected as
209     * being directly between the source and destination mast. The order of the
210     * control masts in the list is the order in which they are connected.
211     *
212     * @param destination controlled signal mast
213     * @return A list of signal mast objects
214     */
215    List<SignalMast> getAutoMasts(SignalMast destination);
216
217    /**
218     * Return the Set State (Aspect) of a control mast as it is configured
219     * between the source and destination mast.
220     *
221     * @param mast        The Control Signal Mast
222     * @param destination controlled signal mast
223     * @return The name of the Aspect the Control Mast should display
224     */
225    @CheckForNull
226    String getAutoSignalMastState(SignalMast mast, SignalMast destination);
227
228    /**
229     * Return the Set State of a control turnout as it is configured between the
230     * source and destination mast.
231     *
232     * @param turnout     The Control Turnout
233     * @param destination controlled signal mast
234     * @return The name of the Aspect the Control Mast should display
235     */
236    int getAutoTurnoutState(Turnout turnout, SignalMast destination);
237
238    /**
239     * Return only the turnouts that have been detected as being directly
240     * between the source and destination mast. The order of the turnouts in the
241     * list is the order in which they are connected.
242     *
243     * @param destination controlled signal mast
244     * @return A list of turnout objects
245     */
246    @Nonnull
247    List<Turnout> getAutoTurnouts(SignalMast destination);
248
249    /**
250     * Return the Set To State of a control block as it is configured between
251     * the source and destination mast.
252     *
253     * @param block       The Control Layout Block
254     * @param destination controlled signal mast
255     * @return Integer representing the state the control block should be in
256     */
257    int getBlockState(Block block, SignalMast destination);
258
259    /**
260     * Return the Layout Blocks that have been defined by the user to control
261     * the SML to the destination mast.
262     *
263     * @param destination controlled signal mast
264     * @return A list of Block objects
265     */
266    @Nonnull
267    List<Block> getBlocks(SignalMast destination);
268
269    /**
270     * Get the comment set on this SML.
271     *
272     * @param destination the mast to get the comment from
273     * @return the comment or an empty string
274     */
275    @Nonnull
276    String getComment(SignalMast destination);
277
278    /**
279     * Return a list of all Signal Masts that have been configured as
280     * Destination Masts on this SML.
281     *
282     * @return A list of Signal Mast objects
283     */
284    @Nonnull
285    List<SignalMast> getDestinationList();
286
287    /**
288     * Get the Maximum Speed set for the destination Signal Mast in this SML.
289     *
290     * @param destination the destination mast
291     * @return A number representing the speed
292     */
293    float getMaximumSpeed(SignalMast destination);
294
295    /**
296     * Return the number of current listeners defined on this SML.
297     *
298     * @return the number of listeners; -1 if the information is not available
299     *         for some reason.
300     */
301    @Override
302    int getNumPropertyChangeListeners();
303
304    /**
305     * Return the Set To State of a control Sensor as it is configured between
306     * the source and destination mast.
307     *
308     * @param sensor      The Control Sensor
309     * @param destination controlled signal mast
310     * @return Integer representing the state the control Sensor should be in
311     */
312    int getSensorState(Sensor sensor, SignalMast destination);
313
314    /**
315     * Return the Sensors that have been defined by the user to control the SML
316     * to the destination mast.
317     *
318     * @param destination controlled signal mast
319     * @return A list of Sensor objects
320     */
321    @Nonnull
322    List<Sensor> getSensors(SignalMast destination);
323
324    /**
325     * Return the Sensors that have been defined by the user to control the SML
326     * to the destination mast as NamedBeanHandles.
327     *
328     * @param destination controlled signal mast
329     * @return A list of Sensor NamedBeanHandles
330     */
331    @Nonnull
332    List<NamedBeanHandle<Sensor>> getNamedSensors(SignalMast destination);
333
334    /**
335     * Return the Set To State (Aspect) of a control Signal Mast as it is
336     * configured between the source and destination mast.
337     *
338     * @param mast        The Control Signal Mast
339     * @param destination controlled signal mast
340     * @return Integer representing the state the control Signal Mast should be
341     *         in
342     */
343    String getSignalMastState(SignalMast mast, SignalMast destination);
344
345    /**
346     * Return the Signal Masts that have been defined by the user to control the
347     * SML to the destination mast.
348     *
349     * @param destination controlled signal mast
350     * @return A list of Signal Mast objects
351     */
352    @Nonnull
353    List<SignalMast> getSignalMasts(SignalMast destination);
354
355    /**
356     * Get the Source Mast.
357     * @return Signal Mast object.
358     */ 
359    @Nonnull
360    SignalMast getSourceMast();
361
362    /**
363     * Return the Set State of a control Turnout as it is configured between the
364     * source and destination mast.
365     *
366     * @param turnout     The Control Turnout
367     * @param destination controlled signal mast
368     * @return Integer representing the state the control Sensor should be in
369     */
370    int getTurnoutState(Turnout turnout, SignalMast destination);
371
372    /**
373     * Return the Turnouts that have been defined by the user to control the SML
374     * to the destination mast.
375     *
376     * @param destination controlled signal mast
377     * @return A list of Turnout objects
378     */
379    @Nonnull
380    List<Turnout> getTurnouts(SignalMast destination);
381
382    /**
383     * Return the Turnouts that have been defined by the user to control the SML
384     * to the destination mast as NamedBeanHandles.
385     *
386     * @param destination controlled signal mast
387     * @return A list of Turnout NamedBeanHandles
388     */
389    @Nonnull
390    List<NamedBeanHandle<Turnout>> getNamedTurnouts(SignalMast destination);
391
392    /**
393     * General method to initialise all SMLs on the source SIgnal Mast using
394     * destList
395     */
396    void initialise();
397
398    /**
399     * Initialise the signal mast after all the parameters have been set.
400     *
401     * @param destination controlled signal mast
402     */
403    void initialise(SignalMast destination);
404
405    /**
406     * Query if the Signal Mast Logic from the current source signal mast to the
407     * destination signal mast is active.
408     *
409     * @param destination controlled signal mast
410     * @return true if active; false otherwise
411     */
412    boolean isActive(SignalMast destination);
413
414    /**
415     * Get the active destination Signal Mast for this Signal Mast Logic.
416     *
417     * @return the active signal mast or null if none
418     */
419    @CheckForNull
420    SignalMast getActiveDestination();
421
422    /**
423     * Check whether the Block is part of at least one of the logics.
424     *
425     * @param block       a layout block
426     * @param destination controlled signal mast
427     * @return true if block is included in any of the Signal Mast Logics that
428     *         set destination
429     */
430    boolean isBlockIncluded(Block block, SignalMast destination);
431
432    /**
433     * Check if signal mast is a destination signal mast in one of the logics
434     *
435     * @param destination controlled signal mast
436     * @return true if destination is a destination mast in this object
437     */
438    boolean isDestinationValid(SignalMast destination);
439
440    /**
441     * Query if the Signal Mast Logic from the current source signal mast to the
442     * specified destination signal mast is enabled.
443     *
444     * @param destination controlled signal mast
445     * @return true if enabled
446     */
447    boolean isEnabled(SignalMast destination);
448
449    /**
450     * Check if a sensor is part of at least one of the logics that set a
451     * SignalMast.
452     *
453     * @param sensor      the sensor to check
454     * @param destination controlled signal
455     * @return true if sensor is included in any of the Signal Mast Logics that
456     *         set destination
457     */
458    boolean isSensorIncluded(Sensor sensor, SignalMast destination);
459
460    /**
461     * Check if a signal mast is part of at least one of the logics that set
462     * another signal mast.
463     *
464     * @param signal      the signal mast to check
465     * @param destination controlled signal mast
466     * @return true if signal is included in any of the Signal Mast Logics that
467     *         set destination
468     */
469    boolean isSignalMastIncluded(SignalMast signal, SignalMast destination);
470
471    /**
472     * Check if a turnout is part of at least one of the logics that set a
473     * signal mast.
474     *
475     * @param turnout     the turnout to check
476     * @param destination controlled signal mast
477     * @return true if turnout is included in any of the Signal Mast Logics that
478     *         set destination
479     */
480    boolean isTurnoutIncluded(Turnout turnout, SignalMast destination);
481
482    /**
483     * Query if we are allowing the system to lock turnouts when the logic goes
484     * active.
485     *
486     * @param destination controlled signal mast
487     * @return true if locking is allowed.
488     */
489    boolean isTurnoutLockAllowed(SignalMast destination);
490
491    /**
492     * Remove control elements for a SML pair containing a destination signal
493     * mast that itself is incompatible with an SML around a level crossing.
494     *
495     * @param sm The destination Signal Mast
496     * @param lx The LevelXing Layout Editor element
497     */
498    void removeConflictingLogic(SignalMast sm, LevelXing lx);
499
500    /**
501     * Remove the destination signal mast as a pair in this SML.
502     *
503     * @param destination controlled signal mast
504     * @return true if there are no more destination signal masts
505     */
506    boolean removeDestination(SignalMast destination);
507
508    /**
509     * Set which blocks must be in a given state for the signal mast not to be
510     * set to a Stop aspect. These blocks are not stored in the panel file.
511     *
512     * @param blocks      map of {@link Block}s and their respective set to
513     *                    state to be checked
514     * @param destination controlled signal mast
515     */
516    void setAutoBlocks(LinkedHashMap<Block, Integer> blocks, SignalMast destination);
517
518    /**
519     * Set which control signal masts must be in a given state before our source
520     * mast can be set. These Signal Masts are not stored in the panel file.
521     *
522     * @param masts       list of control signal masts and their respective set
523     *                    to state to be checked
524     * @param destination controlled signal mast
525     */
526    void setAutoMasts(Hashtable<SignalMast, String> masts, SignalMast destination);
527
528    /**
529     * Set which turnouts must be set to a given state for the signal mast not
530     * to be set to a Stop aspect. These Turnouts are not stored in the panel
531     * file.
532     *
533     * @param turnouts    map of turnouts and their respective set to state
534     * @param destination controlled signal mast
535     */
536    void setAutoTurnouts(Hashtable<Turnout, Integer> turnouts, SignalMast destination);
537
538    /**
539     * Set which blocks must be in a given state for the signal mast not to be
540     * set to a Stop aspect.
541     *
542     * @param blocks      map of Blocks and their respective set to state
543     * @param destination controlled signal mast
544     */
545    void setBlocks(Hashtable<Block, Integer> blocks, SignalMast destination);
546
547    /**
548     * Set the comment for this SML.
549     *
550     * @param comment     text to add as comment
551     * @param destination signal mast to add comment to
552     */
553    void setComment(String comment, SignalMast destination);
554
555    /**
556     * Add control elements for a SML pair containing a destination signal mast
557     * that itself is skipped as it is incompatible with an SML around a level
558     * crossing.
559     *
560     * @param sm The destination Signal Mast
561     * @param lx The LevelXing Layout Editor element
562     */
563    void setConflictingLogic(SignalMast sm, LevelXing lx);
564
565    /**
566     * Set the destination signal mast for this SML.
567     *
568     * @param destination controlled signal mast
569     */
570    void setDestinationMast(SignalMast destination);
571
572    /**
573     * Set the logic to the destination signal mast to Disabled.
574     *
575     * @param destination controlled signal mast
576     */
577    void setDisabled(SignalMast destination);
578
579    /**
580     * Set the logic to the destination signal mast to Enabled.
581     *
582     * @param destination controlled signal mast
583     */
584    void setEnabled(SignalMast destination);
585
586    /**
587     * Set the block facing our source signal mast.
588     *
589     * @param facing The Layout Block facing the source Signal Mast
590     */
591    void setFacingBlock(LayoutBlock facing);
592
593    /**
594     * Get the block defined as facing our source signal mast.
595     *
596     * @return The Layout Block facing the source Signal Mast
597     */
598    LayoutBlock getFacingBlock();
599
600    /**
601     * Set which control signal masts must be in a given state before our source
602     * mast can be set.
603     *
604     * @param masts       map of control signal masts and respective set to
605     *                    states to be checked
606     * @param destination controlled signal mast
607     */
608    void setMasts(Hashtable<SignalMast, String> masts, SignalMast destination);
609
610    /**
611     * Set which sensors must be in a given state before our source signal mast
612     * can be set.
613     *
614     * @param sensors     The {@link Sensor}s to be checked
615     * @param destination controlled signal mast
616     */
617    void setSensors(Hashtable<NamedBeanHandle<Sensor>, Integer> sensors, SignalMast destination);
618
619    /**
620     * Add an individual control Sensor and its set to state to the Signal Mast
621     * Logic.
622     *
623     * @param sensorName  The sensor to be removed
624     * @param state       Integer representing the state the control Sensor
625     *                    should be in
626     * @param destination controlled signal mast
627     */
628    void addSensor(String sensorName, int state, SignalMast destination);
629
630    /**
631     * Remove an individual control Sensor from the Signal Mast Logic.
632     *
633     * @param sensorName  The sensor to be removed
634     * @param destination controlled signal mast
635     */
636    void removeSensor(String sensorName, SignalMast destination);
637
638    /**
639     * Determine if the signal mast logic is stored in the panel file and if all
640     * the information is stored.
641     *
642     * @param store       one of {@link #STOREALL}, {@link #STOREMASTSONLY} or
643     *                    {@link #STORENONE}
644     * @param destination controlled signal mast
645     */
646    void setStore(int store, SignalMast destination);
647
648    /**
649     * Return where the signal mast logic should be stored, if so how much.
650     *
651     * @param destination controlled signal mast
652     * @return one of {@link #STOREALL}, {@link #STOREMASTSONLY} or
653     *         {@link #STORENONE}
654     */
655    int getStoreState(SignalMast destination);
656
657    /**
658     * Set the states that each control turnout must be in for the source signal
659     * mast not to be set to a Stop aspect.
660     *
661     * @param turnouts    A list of named turnouts and their respective set to
662     *                    state to check
663     * @param destination controlled signal mast
664     */
665    void setTurnouts(Hashtable<NamedBeanHandle<Turnout>, Integer> turnouts, SignalMast destination);
666
667    /**
668     * Set up a Signal Mast Logic from the Layout Editor panel where its source
669     * Signal Mast is present, when useLayoutEditor is set to true.
670     */
671    void setupLayoutEditorDetails();
672
673    /**
674     * Set whether this logic should use the details stored in the Layout Editor
675     * to determine which blocks, turnouts will make up the logic between the
676     * source and destination signal mast.
677     *
678     * @param boo         Use the Layout Editor details to determine logic
679     *                    details
680     * @param destination the Destination Signal Mast
681     * @throws jmri.JmriException if a path on the layout editor is not valid
682     */
683    void useLayoutEditor(boolean boo, SignalMast destination) throws JmriException;
684
685    /**
686     * Query if we are using the Layout Editor panels to build the signal mast
687     * logic, blocks, turnouts.
688     *
689     * @param destination Destination Signal Mast
690     * @return true if we are using the Layout Editor to build the signal mast
691     *         logic.
692     */
693    boolean useLayoutEditor(SignalMast destination);
694
695    /**
696     * Query if we are using the Layout Editor block information in the signal
697     * mast logic.
698     *
699     * @param destination Destination Signal Mast
700     * @return true if we are using the block information from the Layout
701     *         Editor.
702     */
703    boolean useLayoutEditorBlocks(SignalMast destination);
704
705    /**
706     * Set whether this logic should use the information from the Layout Editor
707     * for either blocks or turnouts.
708     *
709     * @param turnouts    set false if not to use the turnout information
710     *                    gathered from the layout editor
711     * @param blocks      set false if not to use the block information gathered
712     *                    from the layout editor
713     * @param destination Destination Signal Mast
714     * @throws jmri.JmriException if a path on the layout editor is not valid
715     */
716    void useLayoutEditorDetails(boolean turnouts, boolean blocks, SignalMast destination) throws JmriException;
717
718    /**
719     * Query if we are using the Layout Editor turnout information in the signal
720     * mast logic.
721     *
722     * @param destination controlled signal mast
723     * @return true if we are using the turnout information from the Layout
724     *         Editor.
725     */
726    boolean useLayoutEditorTurnouts(SignalMast destination);
727
728    /**
729     * Set direction sensors in SML need to autoActiveTrains.
730     * @return number of errors
731     */
732    int setupDirectionSensors();
733
734    /**
735     * remove direction sensors from SML need to autoActiveTrains.
736     */
737    void removeDirectionSensors();
738
739    void disableLayoutEditorUse();
740
741    @Override
742    void removePropertyChangeListener(java.beans.PropertyChangeListener l);
743
744    @Override
745    void addPropertyChangeListener(java.beans.PropertyChangeListener l);
746
747    /**
748     * Get the block that the source signal is protecting on the path to the
749     * destination signal mast.
750     *
751     * @param destination controlled signal mast
752     * @return the Layout Block
753     */
754    @CheckForNull
755    LayoutBlock getProtectingBlock(SignalMast destination);
756
757    /**
758     * Set the auto turnouts based upon a given list of layout blocks for a
759     * specific destination mast.
760     *
761     * @param blks        List of Layout Blocks.
762     * @param destination Destination Signal Mast
763     * @return A LinkedHashMap of the original blocks and their required state,
764     *         plus any blocks found on double cross-overs that also need to be
765     *         un-occupied.
766     */
767    @Nonnull
768    LinkedHashMap<Block, Integer> setupLayoutEditorTurnoutDetails(List<LayoutBlock> blks, SignalMast destination);
769
770    @Override
771    void vetoableChange(java.beans.PropertyChangeEvent evt) throws java.beans.PropertyVetoException;
772
773}