001package jmri;
002
003import java.util.ArrayList;
004
005/**
006 * A Transit is a group of Sections representing a specified path through a
007 * layout.
008 * <p>
009 * A Transit may have the following states:
010 * <dl>
011 * <dt>IDLE</dt>
012 * <dd>available for assignment to a train</dd>
013 * <dt>ASSIGNED</dt>
014 * <dd>linked to a train in an {@link jmri.jmrit.dispatcher.ActiveTrain}</dd>
015 * </dl>
016 * <p>
017 * When assigned to a Transit, options may be set for the assigned Section. The
018 * Section and its options are kept in a {@link jmri.TransitSection} object.
019 * <p>
020 * To accommodate passing sidings and other track features, there may be
021 * multiple Sections connecting two other Sections in a Transit. If so, one
022 * Section is assigned as primary, and the other connecting Sections are
023 * assigned as alternates.
024 * <p>
025 * A Section may be in a Transit more than once, for example if a train is to
026 * make two or more loops around a layout before going elsewhere.
027 * <p>
028 * A Transit is normally traversed in the forward direction, that is, the
029 * direction of increasing Section Numbers. When a Transit traversal is started
030 * up, it is always started in the forward direction. However, to accommodate
031 * point-to-point (back and forth) route designs, the direction of travel in a
032 * Transit may be "reversed". While the Transit direction is "reversed", the
033 * direction of travel is the direction of decreasing Section numbers. Whether a
034 * Transit is in the "reversed" direction is kept in the ActiveTrain using the
035 * Transit.
036 *
037 * @author Dave Duchamp Copyright (C) 2008-2011
038 */
039public interface Transit extends NamedBean {
040
041    /**
042     * The idle, or available for assignment to an ActiveTrain state.
043     */
044    int IDLE = 0x02;
045    /**
046     * The assigned to an ActiveTrain state.
047     */
048    int ASSIGNED = 0x04;
049
050    /**
051     * Set the state of this Transit.
052     *
053     * @param state {@link #IDLE} or {@link #ASSIGNED}
054     */
055    @Override
056    void setState(int state);
057
058    /**
059     * Add a Section to this Transit.
060     *
061     * @param s the Section object to add
062     */
063    void addTransitSection(TransitSection s);
064
065    /**
066     * Get the list of TransitSections.
067     *
068     * @return a copy of the internal list of TransitSections or an empty list
069     */
070    ArrayList<TransitSection> getTransitSectionList();
071
072    /**
073     * Get the maximum sequence number used in this Transit.
074     *
075     * @return the maximum sequence
076     */
077    int getMaxSequence();
078
079    /**
080     * Remove all TransitSections in this Transit.
081     */
082    void removeAllSections();
083
084    /**
085     * Check if a Section is in this Transit.
086     *
087     * @param s the section to check for
088     * @return true if the section is present; false otherwise
089     */
090    boolean containsSection(Section s);
091
092    /**
093     * Get a List of Sections with a given sequence number.
094     *
095     * @param seq the sequence number
096     * @return the list of of matching sections or an empty list if none
097     */
098    ArrayList<Section> getSectionListBySeq(int seq);
099
100    /**
101     * Get a List of TransitSections with a given sequence number.
102     *
103     * @param seq the sequence number
104     * @return the list of of matching sections or an empty list if none
105     */
106    ArrayList<TransitSection> getTransitSectionListBySeq(int seq);
107
108    /**
109     * Get a List of sequence numbers for a given Section.
110     *
111     * @param s the section to match
112     * @return the list of matching sequence numbers or an empty list if none
113     */
114    ArrayList<Integer> getSeqListBySection(Section s);
115
116    /**
117     * Check if a Block is in this Transit.
118     *
119     * @param block the block to check for
120     * @return true if block is present; false otherwise
121     */
122    boolean containsBlock(Block block);
123
124    /**
125     * Get the number of times a Block is in this Transit.
126     *
127     * @param block the block to check for
128     * @return the number of times block is present; 0 if block is not present
129     */
130    int getBlockCount(Block block);
131
132    /**
133     * Get a Section from one of its Blocks and its sequence number.
134     *
135     * @param b   the block within the Section
136     * @param seq the sequence number of the Section
137     * @return the Section or null if no matching Section is present
138     */
139    Section getSectionFromBlockAndSeq(Block b, int seq);
140
141    /**
142     * Get Section from one of its EntryPoint Blocks and its sequence number.
143     *
144     * @param b   the connecting block to the Section
145     * @param seq the sequence number of the Section
146     * @return the Section or null if no matching Section is present
147     */
148    Section getSectionFromConnectedBlockAndSeq(Block b, int seq);
149
150    /**
151     * Get the direction of a Section in the transit from its sequence number.
152     *
153     * @param s   the Section to check
154     * @param seq the sequence number of the Section
155     * @return the direction of the Section (one of {@link jmri.Section#FORWARD}
156     *         or {@link jmri.Section#REVERSE} or zero if s and seq are not in a
157     *         TransitSection together
158     */
159    int getDirectionFromSectionAndSeq(Section s, int seq);
160
161    /**
162     * Get a TransitSection in the transit from its Section and sequence number.
163     *
164     * @param s   the Section to check
165     * @param seq the sequence number of the Section
166     * @return the transit section or null if not found
167     */
168    TransitSection getTransitSectionFromSectionAndSeq(Section s, int seq);
169
170    /**
171     * Get a list of all blocks internal to this Transit. Since Sections may be
172     * present more than once, blocks may be listed more than once. The sequence
173     * numbers of the Section the Block was found in are accumulated in a
174     * parallel list, which can be accessed by immediately calling
175     * {@link #getBlockSeqList()}.
176     *
177     * @return the list of all Blocks or an empty list if none are present
178     */
179    ArrayList<Block> getInternalBlocksList();
180
181    /**
182     * Get a list of sequence numbers in this Transit. This list is generated by
183     * calling {@link #getInternalBlocksList()} or
184     * {@link #getEntryBlocksList()}.
185     *
186     * @return the list of all sequence numbers or an empty list if no Blocks
187     *         are present
188     */
189    ArrayList<Integer> getBlockSeqList();
190
191    /**
192     * Get a list of all entry Blocks to this Transit. These are Blocks that a
193     * Train might enter from and be going in the direction of this Transit. The
194     * sequence numbers of the Section the Block will enter are accumulated in a
195     * parallel list, which can be accessed by immediately calling
196     * {@link #getBlockSeqList()}.
197     *
198     * @return the list of all blocks or an empty list if none are present
199     */
200    ArrayList<Block> getEntryBlocksList();
201
202    /**
203     * Get a list of all destination blocks that can be reached from a specified
204     * starting block. The sequence numbers of the Sections destination blocks
205     * were found in are accumulated in a parallel list, which can be accessed
206     * by immediately calling {@link #getDestBlocksSeqList()}.
207     * <p>
208     * <strong>Note:</strong> A Train may not terminate in the same Section in
209     * which it starts.
210     * <p>
211     * <strong>Note:</strong> A Train must terminate in a Block within the
212     * Transit.
213     *
214     * @param startBlock     the starting Block to find destinations for
215     * @param startInTransit true if startBlock is within this Transit; false
216     *                       otherwise
217     * @return a list of destination Blocks or an empty list if none exist
218     */
219    ArrayList<Block> getDestinationBlocksList(Block startBlock, boolean startInTransit);
220
221    /**
222     * Get a list of destination Block sequence numbers in this Transit. This
223     * list is generated by calling
224     * {@link #getDestinationBlocksList(jmri.Block, boolean)}.
225     *
226     * @return the list of all destination Block sequence numbers or an empty
227     *         list if no destination Blocks are present
228     */
229    ArrayList<Integer> getDestBlocksSeqList();
230
231    /**
232     * Check if this Transit is capable of continuous running.
233     * <p>
234     * A Transit is capable of continuous running if, after an Active Train
235     * completes the Transit, it can automatically be restarted. To be
236     * restartable, the first Section and the last Section must be the same
237     * Section, and the first and last Sections must be defined to run in the
238     * same direction. If the last Section is an alternate Section, the previous
239     * Section is tested. However, if the Active Train does not complete its
240     * Transit in the same Section it started in, the restart will not take
241     * place.
242     *
243     * @return true if continuous running is possible; otherwise false
244     */
245    boolean canBeResetWhenDone();
246
247    /**
248     * Initialize blocking sensors for Sections in this Transit. This should be
249     * done before any Sections are allocated for this Transit. Only Sections
250     * that are {@link jmri.Section#FREE} are initialized, so as not to
251     * interfere with running active trains. If any Section does not have
252     * blocking sensors, warning messages are logged.
253     *
254     * @return 0 if no errors, number of errors otherwise.
255     */
256    int initializeBlockingSensors();
257
258    void removeTemporarySections();
259
260    boolean removeLastTemporarySection(Section s);
261
262}