001package jmri;
002
003import java.util.ArrayList;
004import java.util.List;
005
006/**
007 * This class holds information and options for a Action to be applied when an
008 * automated train enters, exits, or is inside of a Section in a Transit.
009 * <p>
010 * A TransitSection holds specified TrainsitSectionActions. A TransitSection may
011 * have as many TransitSectionActions as appropriate. Each TransitSectionAction
012 * belongs to one and only one TransitSection.
013 * <p>
014 * TransitSectionActions are specified in two parts: 1. The "When" part
015 * specifies when after the automated train enters the Section the action is to
016 * be initiated. Optionally, each "when" may be delayed by a specified time (in
017 * milliseconds). 2. The "What" part specified what action is to occur.
018 * <p>
019 * TransitSectionActions are created and edited in the Transit Table, when
020 * Transits are defined.
021 * <p>
022 * This class provides support for SENSORACTIVE and SENSORINACTIVE "when"'s.
023 *
024 * @author Dave Duchamp Copyright (C) 2009, 2010
025 */
026public class TransitSectionAction {
027
028    /**
029     * Constants representing the "when" (when the action is to be initiated) of
030     * the Action.
031     * 
032     * TODO: Convert to ENUM
033     */
034    public static final int NUM_WHENS = 10; // Must correspond to the number of entries below
035    public static final int SELECTWHEN = 0;
036    public static final int ENTRY = 1;   // On entry to Section
037    public static final int EXIT = 2;   // On exit from Section
038    public static final int BLOCKENTRY = 3; // On entry to specified Block in the Section
039    public static final int BLOCKEXIT = 4; // On exit from specified Block in the Section
040    public static final int TRAINSTOP = 5;  // When train stops
041    public static final int TRAINSTART = 6; // When train starts 
042    public static final int SENSORACTIVE = 7; // When specified Sensor changes to Active
043    public static final int SENSORINACTIVE = 8; // When specified Sensor changtes to Inactive
044    public static final int PRESTARTDELAY = 9; // delays the throttle going from 0
045    public static final int PRESTARTACTION = 10; // Actions timed of prestartdelay
046
047    // other action 'whens" may be defined here
048
049    /**
050     * Constants designating the "what" (the action to be taken) of the Action.
051     * 
052     * TODO: Convert to ENUM
053     */
054    public static final int SELECTWHAT = 0;
055    public static final int PAUSE = 1;    // pause for the number of fast minutes in mDataWhat (e.g. station stop)
056    public static final int SETMAXSPEED = 2; // set maximum train speed to value entered
057    public static final int SETCURRENTSPEED = 3; // set current speed to target speed immediately - no ramping
058    public static final int RAMPTRAINSPEED = 4; // set current speed to target with ramping
059    public static final int TOMANUALMODE = 5; // drop out of automated mode, and allow manual throttle control
060    public static final int SETLIGHT = 6; // set light on or off
061    public static final int STARTBELL = 7;  // start bell (only works with sound decoder, function 1 ON)
062    public static final int STOPBELL = 8;   // stop bell (only works with sound decoder, function 1 OFF)
063    public static final int SOUNDHORN = 9;  // sound horn for specified number of milliseconds 
064    // (only works with sound decoder, function 2)
065    public static final int SOUNDHORNPATTERN = 10; // sound horn according to specified pattern
066    // (only works with sound decoder, function 2)
067    public static final int LOCOFUNCTION = 11;  // execute the specified decoder function
068    public static final int SETSENSORACTIVE = 12; // set specified sensor active (offers access to Logix)
069    public static final int SETSENSORINACTIVE = 13; // set specified sensor inactive
070    public static final int HOLDSIGNAL = 14;    // set specified signalhead or signalmast to HELD
071    public static final int RELEASESIGNAL = 15; // set specified signalhead or signalmast to NOT HELD
072    public static final int ESTOP = 16;   // set ESTOP
073    public static final int PRESTARTRESUME = 17; // Resume after prestart
074    public static final int NUM_WHATS = 17; // Must correspond to the number of entries above
075    // other action 'whats" may be defined above, increment NUM_WHATS to match
076
077    /**
078     * Create a TransitSectionAction.
079     *
080     * @param when one of
081     *             {@link #ENTRY}, {@link #EXIT}, {@link #BLOCKENTRY}, {@link #BLOCKEXIT}, {@link #TRAINSTOP}, {@link #TRAINSTART}, {@link #SENSORACTIVE}, {@link #SENSORINACTIVE}, {@link #PRESTARTRESUME}
082     * @param what one of
083     *             {@link #PAUSE}, {@link #SETMAXSPEED}, {@link #SETCURRENTSPEED}, {@link #RAMPTRAINSPEED}, {@link #TOMANUALMODE}, {@link #SETLIGHT}, {@link #STARTBELL}, {@link #STOPBELL}, {@link #SOUNDHORN}, {@link #SOUNDHORNPATTERN}, {@link #LOCOFUNCTION}, {@link #SETSENSORACTIVE}, {@link #SETSENSORINACTIVE}, {@link #HOLDSIGNAL}, {@link #RELEASESIGNAL}
084     */
085    public TransitSectionAction(int when, int what) {
086        mWhen = when;
087        mWhat = what;
088    }
089
090    /**
091     * Create a TransitSectionAction.
092     *
093     * @param when      one of
094     *                  {@link #ENTRY}, {@link #EXIT}, {@link #BLOCKENTRY}, {@link #BLOCKEXIT}, {@link #TRAINSTOP}, {@link #TRAINSTART}, {@link #SENSORACTIVE}, {@link #SENSORINACTIVE}
095     * @param what      one of
096     *                  {@link #PAUSE}, {@link #SETMAXSPEED}, {@link #SETCURRENTSPEED}, {@link #RAMPTRAINSPEED}, {@link #TOMANUALMODE}, {@link #SETLIGHT}, {@link #STARTBELL}, {@link #STOPBELL}, {@link #SOUNDHORN}, {@link #SOUNDHORNPATTERN}, {@link #LOCOFUNCTION}, {@link #SETSENSORACTIVE}, {@link #SETSENSORINACTIVE}, {@link #HOLDSIGNAL}, {@link #RELEASESIGNAL}
097     * @param dataWhen  a data element for when
098     * @param dataWhat1 a data element for what
099     * @param dataWhat2 a data element for what
100     * @param sWhen     typically a readable description of when or the name of
101     *                  the triggering sensors
102     * @param sWhat     typically a readable description of what
103     */
104    public TransitSectionAction(int when, int what, int dataWhen, int dataWhat1, int dataWhat2, String sWhen, String sWhat) {
105        mWhen = when;
106        mWhat = what;
107        mDataWhen = dataWhen;
108        mDataWhat1 = dataWhat1;
109        mDataWhat2 = dataWhat2;
110        mStringWhen = sWhen;
111        mStringWhat = sWhat;
112    }
113
114
115    // instance variables
116    private int mWhen = 0;
117    private int mWhat = 0;
118    private int mDataWhen = -1; // negative number signified no data 
119    private int mDataWhat1 = -1;    // negative number signified no data 
120    private float mDataWhat1Float = -1.0f;
121    private int mDataWhat2 = -1;    // negative number signified no data 
122    private String mStringWhen = "";
123    private String mStringWhat = "";
124    private Object threadObject;
125
126    /*
127     * Access methods
128     */
129    public void setThreadObject(Object threadObj) {
130        threadObject = threadObj;
131    }
132    public Object getThreadObject() {
133        return threadObject;
134    }
135    public int getWhenCode() {
136        return mWhen;
137    }
138
139    public void setWhenCode(int n) {
140        mWhen = n;
141    }
142
143    public int getWhatCode() {
144        return mWhat;
145    }
146
147    public void setWhatCode(int n) {
148        mWhat = n;
149    }
150
151    public int getDataWhen() {
152        return mDataWhen;
153    }
154
155    public void setDataWhen(int n) {
156        mDataWhen = n;
157    }
158
159    public float getDataWhat1Float() {
160        return mDataWhat1Float;
161    }
162
163    public void setDataWhat1Float(float n) {
164        mDataWhat1Float = n;
165    }
166
167    public int getDataWhat1() {
168        return mDataWhat1;
169    }
170
171    public void setDataWhat1(int n) {
172        mDataWhat1 = n;
173    }
174
175    public int getDataWhat2() {
176        return mDataWhat2;
177    }
178
179    public void setDataWhat2(int n) {
180        mDataWhat2 = n;
181    }
182
183    public String getStringWhen() {
184        return mStringWhen;
185    }
186
187    public void setStringWhen(String s) {
188        mStringWhen = s;
189    }
190
191    public String getStringWhat() {
192        return mStringWhat;
193    }
194
195    public void setStringWhat(String s) {
196        mStringWhat = s;
197    }
198
199    /*
200     * Operational instance variables - flags and data for executing the action
201     * (see jmri.jmrit.dispatcher.AutoActiveTrain.java)
202     */
203    private Thread _waitingThread = null;
204    private boolean _waitingForSectionExit = false;
205    private TransitSection _targetTransitSection = null;
206    private boolean _waitingForBlock = false;
207    private boolean _waitingForSensor = false;
208    private Sensor _triggerSensor = null;
209    private java.beans.PropertyChangeListener _sensorListener = null;
210
211    /**
212     * Initialize all operational instance variables (not saved between runs).
213     */
214    public void initialize() {
215        _waitingThread = null;
216        _waitingForSectionExit = false;
217        _targetTransitSection = null;
218        _waitingForBlock = false;
219        _waitingForSensor = false;
220        _triggerSensor = null;
221        _sensorListener = null;
222    }
223
224    /*
225     * Operational access methods
226     */
227    public Thread getWaitingThread() {
228        return _waitingThread;
229    }
230
231    public void setWaitingThread(Thread t) {
232        _waitingThread = t;
233    }
234
235    public boolean getWaitingForSectionExit() {
236        return _waitingForSectionExit;
237    }
238
239    public void setWaitingForSectionExit(boolean w) {
240        _waitingForSectionExit = w;
241    }
242
243    public TransitSection getTargetTransitSection() {
244        return _targetTransitSection;
245    }
246
247    public void setTargetTransitSection(TransitSection ts) {
248        _targetTransitSection = ts;
249    }
250
251    public boolean getWaitingForBlock() {
252        return _waitingForBlock;
253    }
254
255    public void setWaitingForBlock(boolean w) {
256        _waitingForBlock = w;
257    }
258
259    public boolean getWaitingForSensor() {
260        return _waitingForSensor;
261    }
262
263    public void setWaitingForSensor(boolean w) {
264        _waitingForSensor = w;
265    }
266
267    public Sensor getTriggerSensor() {
268        return _triggerSensor;
269    }
270
271    public void setTriggerSensor(Sensor s) {
272        _triggerSensor = s;
273    }
274
275    public java.beans.PropertyChangeListener getSensorListener() {
276        return _sensorListener;
277    }
278
279    public void setSensorListener(java.beans.PropertyChangeListener l) {
280        _sensorListener = l;
281    }
282
283    public void disposeSensorListener() {
284        // if this object has registered a listener, dispose of it
285        if (_sensorListener != null) {
286            _triggerSensor.removePropertyChangeListener(_sensorListener);
287            _sensorListener = null;
288            _waitingForSensor = false;
289        }
290    }
291
292    public void dispose() {
293        disposeSensorListener();
294    }
295
296}