001package jmri;
002
003import java.util.ArrayList;
004import org.slf4j.Logger;
005import org.slf4j.LoggerFactory;
006
007/**
008 * This class holds information and options for a Section when assigned to a
009 * Transit. Corresponds to an allocatable "Section" of track assigned to a
010 * Transit.
011 * <p>
012 * A TransitSection holds the following information: Section ID Section
013 * Direction Sequence number of Section within the Transit Special actions list
014 * for train in this Section, if requested (see TransitSectionAction.java)
015 * Whether this Section is a primary section or an alternate section
016 * <p>
017 * A TransitSection is referenced via a list in its parent Transit, and is
018 * stored on disk when its parent Transit is stored.
019 * <p>
020 * Provides for delayed initialization of Section when loading panel files, so
021 * that this is not dependent on order of items in the panel file.
022 *
023 * @author Dave Duchamp Copyright (C) 2008
024 */
025public class TransitSection {
026
027    /**
028     * Create a TransitSection. This calls the alternate constructor with false
029     * for the alt value.
030     *
031     * @param s         the section to add to the transit
032     * @param seq       the sequence number of the section in the transit
033     * @param direction the direction of travel within the transit
034     */
035    public TransitSection(jmri.Section s, int seq, int direction) {
036        this(s, seq, direction, false);
037    }
038
039    /**
040     * Create an alternate or primary TransitSection.
041     *
042     * @param s         the section to add to the transit
043     * @param seq       the sequence number of the section in the transit
044     * @param direction the direction of travel within the transit
045     * @param alt       true if the section is an alternate; false if section is
046     *                  primary or has no alternates
047     */
048    public TransitSection(jmri.Section s, int seq, int direction, boolean alt) {
049        mSection = s;
050        mSequence = seq;
051        mDirection = direction;
052        mAlternate = alt;
053    }
054
055    /**
056     * Create an alternate or primary TransitSection, and defined as safe or not
057     *
058     * @param s         the section to add to the transit
059     * @param seq       the sequence number of the section in the transit
060     * @param direction the direction of travel within the transit
061     * @param alt       true if the section is an alternate; false if section is
062     *                  primary or has no alternates
063     * @param safe      true if this is a safe section. When dispatcher by safe sections
064     *                  a train is dispatched safe section to safe section with all intervening sections available.
065     * @param stopAllocatingSensorName If this sensor is present, valid, and Active allocation will stop until
066     *                  it is no longer Active.
067     * @param fwdStopPerCent The distance into the section when traveling fwd thru the transit.
068     * @param revStopPerCent The distance into the section when traveling rev thru the transit.
069     */
070    public TransitSection(jmri.Section s, int seq, int direction, boolean alt, boolean safe,
071            String stopAllocatingSensorName, float fwdStopPerCent, float revStopPerCent) {
072        mSection = s;
073        mSequence = seq;
074        mDirection = direction;
075        mAlternate = alt;
076        mSafe = safe;
077        mStopAllocatingSensorName = stopAllocatingSensorName;
078        mFwdStopPerCent = fwdStopPerCent;
079        mRevStopPerCent = revStopPerCent;
080    }
081
082    /**
083     * Create an alternate or primary TransitSection with a delayed
084     * initialization.
085     *
086     * @param secName   the name of the section to add to the transit
087     * @param seq       the sequence number of the section in the transit
088     * @param direction the direction of travel within the transit
089     * @param alt       true if the section is an alternate; false if section is
090     *                  primary or has no alternates
091     */
092    public TransitSection(String secName, int seq, int direction, boolean alt) {
093        tSectionName = secName;
094        mSequence = seq;
095        mDirection = direction;
096        mAlternate = alt;
097        needsInitialization = true;
098    }
099
100    /**
101     * Create an alternate or primary TransitSection with a delayed
102     * initialization.
103     *
104     * @param secName   the name of the section to add to the transit
105     * @param seq       the sequence number of the section in the transit
106     * @param direction the direction of travel within the transit
107     * @param alt       true if the section is an alternate; false if section is
108     *                  primary or has no alternates
109     * @param safe      true if this is a safe section. When dispatcher by safe sections
110     *                  a train is dispatched safe section to safe section with all intervening sections available.
111     * @param stopAllocatingSensorName If this sensor is present, valid, and Active allocation will stop until
112     *                  it is no longer Active.
113     * @param fwdStopPerCent The distance into the section when traveling fwd thru the transit.
114     * @param revStopPerCent The distance into the section when traveling rev thru the transit.
115     */
116    public TransitSection(String secName, int seq, int direction, boolean alt,
117            boolean safe, String stopAllocatingSensorName, float fwdStopPerCent,
118            float revStopPerCent) {
119        tSectionName = secName;
120        mSequence = seq;
121        mDirection = direction;
122        mAlternate = alt;
123        mSafe = safe;
124        mStopAllocatingSensorName = stopAllocatingSensorName;
125        mFwdStopPerCent = fwdStopPerCent;
126        mRevStopPerCent = revStopPerCent;
127        needsInitialization = true;
128    }
129
130    // instance variables
131    private Section mSection = null;
132    private int mSequence = 0;
133    private int mDirection = 0;
134    private final ArrayList<TransitSectionAction> mTransitSectionActionList = new ArrayList<>();
135    private boolean mAlternate = false;
136    private boolean mSafe = false;
137    private String mStopAllocatingSensorName = "";
138    private float mFwdStopPerCent;
139    private float mRevStopPerCent;
140
141    // temporary variables and method for delayed initialization of Section
142    private String tSectionName = "";
143    private boolean needsInitialization = false;
144
145    private void initialize() {
146        if (tSectionName.equals("null")) {
147            log.error("Null Section Name when initializing a TransitSection");
148        } else {
149            mSection = InstanceManager.getDefault(jmri.SectionManager.class).getSection(tSectionName);
150            if (mSection == null) {
151                log.error("Missing Section - {} - when initializing a TransitSection", tSectionName);
152            }
153        }
154        needsInitialization = false;
155    }
156
157    private boolean temporary = false;
158
159    public void setTemporary(boolean boo) {
160        temporary = boo;
161    }
162
163    public boolean isTemporary() {
164        return temporary;
165    }
166
167    /**
168     * Get the associated section.
169     *
170     * @return the section or null if no section is associated with this
171     *         TransitSection
172     */
173    public Section getSection() {
174        if (needsInitialization) {
175            initialize();
176        }
177        return mSection;
178    }
179
180    public String getSectionName() {
181        if (needsInitialization) {
182            initialize();
183        }
184        String s = mSection.getSystemName();
185        String u = mSection.getUserName();
186        if ((u != null) && (!u.isEmpty())) {
187            return (s + "( " + u + " )");
188        }
189        return s;
190    }
191
192    // Note: once TransitSection is created, Section and its sequence and direction may not be changed.
193    public int getDirection() {
194        return mDirection;
195    }
196
197    public int getSequenceNumber() {
198        return mSequence;
199    }
200
201    public void addAction(TransitSectionAction act) {
202        mTransitSectionActionList.add(act);
203    }
204
205    public boolean isAlternate() {
206        return mAlternate;
207    }
208
209    public void setAlternate(boolean alt) {
210        mAlternate = alt;
211    }
212
213    public boolean isSafe() {
214        return mSafe;
215    }
216
217    public void setSafe(boolean safe) {
218        mSafe = safe;
219    }
220
221    public String getStopAllocatingSensor() {
222        return mStopAllocatingSensorName;
223    }
224
225    public void setStopAllocatingSensor(String stopAllocatingSensor ) {
226        mStopAllocatingSensorName = stopAllocatingSensor;
227    }
228
229    /**
230     * Sets the stopping distance percentage of section when transit allocated fwd.
231     * @param val length as a percentage of section;
232     */
233    public void setFwdStopPerCent(float val) {
234        mFwdStopPerCent = val;
235    }
236
237    /**
238     * Returns the stopping distance percentage of section when transit allocated fwd.
239     */
240    public float getFwdStopPerCent() {
241        return mFwdStopPerCent;
242    }
243
244    /**
245     * Sets actual distance percentage of section when transit allocated fwd.
246     * @param val length as a percentage of section;
247     */
248    public void setRevStopPerCent(float val) {
249        mRevStopPerCent = val;
250    }
251
252    /**
253     * Returns the stopping distance percentage of section when transit allocated rev.
254     */
255    public float getRevStopPerCent() {
256        return mRevStopPerCent;
257    }
258
259    /**
260     * Get a list of the actions for this TransitSection
261     *
262     * @return a list of actions or an empty list if there are no actions
263     */
264    public ArrayList<TransitSectionAction> getTransitSectionActionList() {
265        return new ArrayList<>(mTransitSectionActionList);
266    }
267
268    private final static Logger log = LoggerFactory.getLogger(TransitSection.class);
269}