001package jmri;
002
003import java.beans.PropertyChangeEvent;
004import java.beans.PropertyChangeListener;
005import java.util.List;
006import java.util.ArrayList;
007import java.util.Arrays;
008import java.util.Collections;
009import java.util.Set;
010import java.util.HashSet;
011import java.util.ResourceBundle;
012
013import javax.annotation.CheckForNull;
014import javax.annotation.Nonnull;
015
016/**
017 * A Conditional is layout control logic, consisting of a logical expression and
018 * an action.
019 * <p>
020 * A Conditional does not exist on its own, but is part of a Logix.
021 * The system name of each Conditional is set automatically when the conditional
022 * is created.
023 * It begins with the system name of its parent Logix.
024 * There is no Conditional Table.
025 * Conditionals are created, edited, and deleted via the Logix Table.
026 * <p>
027 * A Conditional has a "state", which changes depending on whether its logical
028 * expression calculates to TRUE or FALSE.
029 * The "state" may not be changed by the user.
030 * It only changes in response to changes in the "state variables" used in
031 * its logical expression.
032 * <p>
033 * Listeners may be set to monitor a change in the state of a conditional.
034 *
035 * <hr>
036 * This file is part of JMRI.
037 * <p>
038 * JMRI is free software; you can redistribute it and/or modify it under the
039 * terms of version 2 of the GNU General Public License as published by the Free
040 * Software Foundation. See the "COPYING" file for a copy of this license.
041 * <p>
042 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
043 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
044 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
045 *
046 * @author Dave Duchamp Copyright (C) 2007, 2008
047 * @author Pete Cressman Copyright (C) 2009, 2010, 2011
048 * @author Matthew Harris copyright (c) 2009
049 */
050public interface Conditional extends NamedBean {
051
052    ResourceBundle rbx = ResourceBundle.getBundle("jmri.jmrit.conditional.ConditionalBundle");
053    ResourceBundle rbxWarrant = ResourceBundle.getBundle("jmri.jmrit.logix.WarrantBundle");
054
055    // states
056    @SuppressWarnings("hiding")     // Field has same name as a field in the super class
057    enum State {
058        UNKNOWN(NamedBean.UNKNOWN, "StateUnknown"),
059        FALSE(Conditional.FALSE, "StateFalse"),
060        TRUE(Conditional.TRUE, "StateTrue");
061
062        private final int _state;
063        private final String _bundleKey;
064
065        private State(int state, String bundleKey) {
066            _state = state;
067            _bundleKey = bundleKey;
068        }
069
070        public int getIntValue() {
071            return _state;
072        }
073
074        public static State getOperatorFromIntValue(int stateInt) {
075            for (State state : State.values()) {
076                if (state.getIntValue() == stateInt) {
077                    return state;
078                }
079            }
080
081            throw new IllegalArgumentException("State is unknown");
082        }
083
084        @Override
085        public String toString() {
086            return Bundle.getMessage(_bundleKey);
087        }
088    }
089
090    int FALSE = 0x02;
091    int TRUE = 0x04;
092
093    @SuppressWarnings("hiding")     // Field has same name as a field in the super class
094    public enum AntecedentOperator {
095        ALL_AND(Conditional.ALL_AND, Bundle.getMessage("LogicAND")),
096        ALL_OR(Conditional.ALL_OR, Bundle.getMessage("LogicOR")),
097        MIXED(Conditional.MIXED, Bundle.getMessage("LogicMixed"));
098
099        private final int _value;
100        private final String _string;
101
102        AntecedentOperator(int value, String string) {
103            _value = value;
104            _string = string;
105        }
106
107        public int getIntValue() {
108            return _value;
109        }
110
111        public static AntecedentOperator getOperatorFromIntValue(int value) {
112            for (AntecedentOperator antecedentOperators : AntecedentOperator.values()) {
113                if (antecedentOperators.getIntValue() == value) {
114                    return antecedentOperators;
115                }
116            }
117
118            throw new IllegalArgumentException("ItemType is unknown");
119        }
120
121        @Override
122        public String toString() {
123            return _string;
124        }
125    }
126
127    // logic operators used in antecedent
128    int ALL_AND = 0x01;
129    int ALL_OR = 0x02;
130    int MIXED = 0x03;
131
132    public enum Operator {
133        NONE,
134        AND,
135        OR;
136
137        // This method is used by DefaultConditionalManagerXml.store() for backward compatibility
138        public int getIntValue() {
139            switch (this) {
140                case NONE: return OPERATOR_NONE;
141                case AND: return OPERATOR_AND;
142                case OR: return OPERATOR_OR;
143                default: throw new IllegalArgumentException(String.format("operator %s is unknown", this.name()));
144            }
145        }
146
147        // This method is used by DefaultConditionalManagerXml.loadConditionals() for backward compatibility
148        public static Operator getOperatorFromIntValue(int opern) {
149            switch (opern) {
150                case OPERATOR_AND: return Operator.AND;
151                case OPERATOR_NONE: return Operator.NONE;
152                case OPERATOR_OR: return Operator.OR;
153                default: throw new IllegalArgumentException(String.format("operator %d is unknown", opern));
154            }
155        }
156    }
157
158    // state variable definitions. Keep these since they are needed
159    // for backward compatibility in DefaultConditionalManagerXml.
160    // But they are not used elsewhere.
161    int OPERATOR_AND = 1;
162    int OPERATOR_NONE = 4;
163    int OPERATOR_OR = 5;
164
165    // state variable and action items used by logix.
166    enum ItemType {
167        NONE(TYPE_NONE, IsStateVar.IS_STATE_VAR, "ItemTypeNone"), // There is no ITEM_TYPE_NONE so use TYPE_NONE instead
168        SENSOR(ITEM_TYPE_SENSOR, IsStateVar.IS_STATE_VAR, "ItemTypeSensor"),
169        TURNOUT(ITEM_TYPE_TURNOUT, IsStateVar.IS_STATE_VAR, "ItemTypeTurnout"),
170        LIGHT(ITEM_TYPE_LIGHT, IsStateVar.IS_STATE_VAR, "ItemTypeLight"),
171        SIGNALHEAD(ITEM_TYPE_SIGNALHEAD, IsStateVar.IS_STATE_VAR, "ItemTypeSignalHead"),
172        SIGNALMAST(ITEM_TYPE_SIGNALMAST, IsStateVar.IS_STATE_VAR, "ItemTypeSignalMast"),
173        MEMORY(ITEM_TYPE_MEMORY, IsStateVar.IS_STATE_VAR, "ItemTypeMemory"),
174        CONDITIONAL(ITEM_TYPE_CONDITIONAL, IsStateVar.IS_STATE_VAR, "ItemTypeConditional"), // used only by ConditionalVariable
175        LOGIX(ITEM_TYPE_LOGIX, IsStateVar.IS_STATE_VAR, "ItemTypeLogix"), // used only by ConditionalAction
176        WARRANT(ITEM_TYPE_WARRANT, IsStateVar.IS_STATE_VAR, "ItemTypeWarrant"),
177        CLOCK(ITEM_TYPE_CLOCK, IsStateVar.IS_STATE_VAR, "ItemTypeClock"),
178        OBLOCK(ITEM_TYPE_OBLOCK, IsStateVar.IS_STATE_VAR, "ItemTypeOBlock"),
179        ENTRYEXIT(ITEM_TYPE_ENTRYEXIT, IsStateVar.IS_STATE_VAR, "ItemTypeEntryExit"),
180
181        AUDIO(ITEM_TYPE_AUDIO, IsStateVar.IS_NOT_STATE_VAR, "ItemTypeAudio"),
182        SCRIPT(ITEM_TYPE_SCRIPT, IsStateVar.IS_NOT_STATE_VAR, "ItemTypeScript"),
183        OTHER(ITEM_TYPE_OTHER, IsStateVar.IS_NOT_STATE_VAR, "ItemTypeOther");
184
185        private final int _type;
186        private final IsStateVar _isStateVar;
187        private final String _bundleKey;
188
189        private static final List<ItemType> stateVarList;
190
191        static
192        {
193            stateVarList = new ArrayList<>();
194
195            for (ItemType itemType : ItemType.values()) {
196                if (itemType.getIsStateVar() == IsStateVar.IS_STATE_VAR) {
197                    stateVarList.add(itemType);
198                }
199            }
200        }
201
202        ItemType(int type, IsStateVar isStateVar, String bundleKey) {
203            _type = type;
204            _isStateVar = isStateVar;
205            _bundleKey = bundleKey;
206        }
207
208        public static List<ItemType> getStateVarList() {
209            return stateVarList;
210        }
211
212        public int getIntValue() {
213            return _type;
214        }
215
216        public static ItemType getOperatorFromIntValue(int itemTypeInt) {
217            for (ItemType itemType : ItemType.values()) {
218                if (itemType.getIntValue() == itemTypeInt) {
219                    return itemType;
220                }
221            }
222
223            throw new IllegalArgumentException("ItemType is unknown");
224        }
225
226        @Override
227        public String toString() {
228            return Bundle.getMessage(_bundleKey);
229        }
230
231        // This enum is only used within the outer enum ItemType.
232        private enum IsStateVar {
233            IS_STATE_VAR,
234            IS_NOT_STATE_VAR
235        }
236
237        private IsStateVar getIsStateVar() {
238            return _isStateVar;
239        }
240
241    }
242
243    // items
244    enum Type {
245        ERROR(TYPE_ERROR, ItemType.NONE, "", ""),
246        NONE(TYPE_NONE, ItemType.NONE, "", ""),
247        SENSOR_ACTIVE(TYPE_SENSOR_ACTIVE, ItemType.SENSOR,
248            Bundle.getMessage("SensorStateActive"), rbx.getString("TypeSensorActive")),
249        SENSOR_INACTIVE(TYPE_SENSOR_INACTIVE, ItemType.SENSOR,
250            Bundle.getMessage("SensorStateInactive"), rbx.getString("TypeSensorInactive")),
251        TURNOUT_THROWN(TYPE_TURNOUT_THROWN, ItemType.TURNOUT,
252            Bundle.getMessage("TurnoutStateThrown"), rbx.getString("TypeTurnoutThrown")),
253        TURNOUT_CLOSED(TYPE_TURNOUT_CLOSED, ItemType.TURNOUT,
254            Bundle.getMessage("TurnoutStateClosed"), rbx.getString("TypeTurnoutClosed")),
255        CONDITIONAL_TRUE(TYPE_CONDITIONAL_TRUE, ItemType.CONDITIONAL,
256            Bundle.getMessage("True"), rbx.getString("TypeConditionalTrue")),
257        CONDITIONAL_FALSE(TYPE_CONDITIONAL_FALSE, ItemType.CONDITIONAL,
258            Bundle.getMessage("False"), rbx.getString("TypeConditionalFalse")),
259        LIGHT_ON(TYPE_LIGHT_ON, ItemType.LIGHT,
260            rbx.getString("LightOn"), rbx.getString("TypeLightOn")),
261        LIGHT_OFF(TYPE_LIGHT_OFF, ItemType.LIGHT,
262            rbx.getString("LightOff"), rbx.getString("TypeLightOff")),
263        MEMORY_EQUALS(TYPE_MEMORY_EQUALS, ItemType.MEMORY,
264            rbx.getString("StateMemoryEquals"), rbx.getString("TypeMemoryEquals")),
265        MEMORY_COMPARE(TYPE_MEMORY_COMPARE, ItemType.MEMORY,
266            rbx.getString("StateMemoryCompare"), rbx.getString("TypeMemoryCompare")),
267        MEMORY_EQUALS_INSENSITIVE(TYPE_MEMORY_EQUALS_INSENSITIVE, ItemType.MEMORY,
268            rbx.getString("StateMemoryEqualsInsensitive"), rbx.getString("TypeMemoryEqualsInsensitive")),
269        MEMORY_COMPARE_INSENSITIVE(TYPE_MEMORY_COMPARE_INSENSITIVE, ItemType.MEMORY,
270            rbx.getString("StateMemoryCompareInsensitive"), rbx.getString("TypeMemoryCompareInsensitive")),
271        FAST_CLOCK_RANGE(TYPE_FAST_CLOCK_RANGE, ItemType.CLOCK,
272            rbx.getString("TypeFastClockRange"), rbx.getString("TypeFastClockRange")),
273
274        // Note the set signalHeadAppearanceSet below which holds those SignalHead types that are appearances.
275        SIGNAL_HEAD_RED(TYPE_SIGNAL_HEAD_RED, ItemType.SIGNALHEAD,
276            Bundle.getMessage("SignalHeadStateRed"), Bundle.getMessage("SignalHeadStateRed")),
277        SIGNAL_HEAD_YELLOW(TYPE_SIGNAL_HEAD_YELLOW, ItemType.SIGNALHEAD,
278            Bundle.getMessage("SignalHeadStateYellow"), Bundle.getMessage("SignalHeadStateYellow")),
279        SIGNAL_HEAD_GREEN(TYPE_SIGNAL_HEAD_GREEN, ItemType.SIGNALHEAD,
280            Bundle.getMessage("SignalHeadStateGreen"), Bundle.getMessage("SignalHeadStateGreen")),
281        SIGNAL_HEAD_DARK(TYPE_SIGNAL_HEAD_DARK, ItemType.SIGNALHEAD,
282            Bundle.getMessage("SignalHeadStateDark"), Bundle.getMessage("SignalHeadStateDark")),
283        SIGNAL_HEAD_FLASHRED(TYPE_SIGNAL_HEAD_FLASHRED, ItemType.SIGNALHEAD,
284            Bundle.getMessage("SignalHeadStateFlashingRed"), Bundle.getMessage("SignalHeadStateFlashingRed")),
285        SIGNAL_HEAD_FLASHYELLOW(TYPE_SIGNAL_HEAD_FLASHYELLOW, ItemType.SIGNALHEAD,
286            Bundle.getMessage("SignalHeadStateFlashingYellow"), Bundle.getMessage("SignalHeadStateFlashingYellow")),
287        SIGNAL_HEAD_FLASHGREEN(TYPE_SIGNAL_HEAD_FLASHGREEN, ItemType.SIGNALHEAD,
288            Bundle.getMessage("SignalHeadStateFlashingGreen"), Bundle.getMessage("SignalHeadStateFlashingGreen")),
289        SIGNAL_HEAD_LIT(TYPE_SIGNAL_HEAD_LIT, ItemType.SIGNALHEAD,
290            Bundle.getMessage("SignalHeadStateLit"), Bundle.getMessage("SignalHeadStateLit")),
291        SIGNAL_HEAD_HELD(TYPE_SIGNAL_HEAD_HELD, ItemType.SIGNALHEAD,
292            Bundle.getMessage("SignalHeadStateHeld"), Bundle.getMessage("SignalHeadStateHeld")),
293        SIGNAL_HEAD_LUNAR(TYPE_SIGNAL_HEAD_LUNAR, ItemType.SIGNALHEAD,
294            Bundle.getMessage("SignalHeadStateLunar"), Bundle.getMessage("SignalHeadStateLunar")),
295        SIGNAL_HEAD_FLASHLUNAR(TYPE_SIGNAL_HEAD_FLASHLUNAR, ItemType.SIGNALHEAD,
296            Bundle.getMessage("SignalHeadStateFlashingLunar"), Bundle.getMessage("SignalHeadStateFlashingLunar")),
297        // Warrant variables
298        ROUTE_FREE(TYPE_ROUTE_FREE, ItemType.WARRANT,
299            rbx.getString("StateRouteFree"), rbx.getString("TypeWarrantRouteFree")),
300        ROUTE_OCCUPIED(TYPE_ROUTE_OCCUPIED, ItemType.WARRANT,
301            rbx.getString("stateRouteOccupied"), rbx.getString("TypeWarrantRouteOccupied")),
302        ROUTE_ALLOCATED(TYPE_ROUTE_ALLOCATED, ItemType.WARRANT,
303            rbx.getString("StateRouteReserved"), rbx.getString("TypeWarrantRouteAllocated")),
304        ROUTE_SET(TYPE_ROUTE_SET, ItemType.WARRANT,
305            rbx.getString("StateRouteIsSet"), rbx.getString("TypeRouteIsSet")),
306        TRAIN_RUNNING(TYPE_TRAIN_RUNNING, ItemType.WARRANT,
307            rbx.getString("StateTrainRunning"), rbx.getString("TypeTrainRunning")),
308        SIGNAL_MAST_ASPECT_EQUALS(TYPE_SIGNAL_MAST_ASPECT_EQUALS, ItemType.SIGNALMAST,
309            rbx.getString("TypeSignalMastAspectEquals"), rbx.getString("TypeSignalMastAspectEquals")),
310        SIGNAL_MAST_LIT(TYPE_SIGNAL_MAST_LIT, ItemType.SIGNALMAST,
311            Bundle.getMessage("SignalMastStateLit"), Bundle.getMessage("SignalMastStateLit")),
312        SIGNAL_MAST_HELD(TYPE_SIGNAL_MAST_HELD, ItemType.SIGNALMAST,
313            Bundle.getMessage("SignalMastStateHeld"), Bundle.getMessage("SignalMastStateHeld")),
314        SIGNAL_HEAD_APPEARANCE_EQUALS(TYPE_SIGNAL_HEAD_APPEARANCE_EQUALS, ItemType.SIGNALHEAD,
315            rbx.getString("TypeSignalHeadAspectEquals"), rbx.getString("TypeSignalHeadAspectEquals")),
316        BLOCK_STATUS_EQUALS(TYPE_BLOCK_STATUS_EQUALS, ItemType.OBLOCK, "", ""),
317        //Entry Exit Rules
318        ENTRYEXIT_ACTIVE(TYPE_ENTRYEXIT_ACTIVE, ItemType.ENTRYEXIT,
319            rbx.getString("TypeEntryExitActive"), rbx.getString("TypeEntryExitActive")),
320        ENTRYEXIT_INACTIVE(TYPE_ENTRYEXIT_INACTIVE, ItemType.ENTRYEXIT,
321            rbx.getString("TypeEntryExitInactive"), rbx.getString("TypeEntryExitInactive")),
322        // OBlock
323        OBLOCK_UNOCCUPIED(TYPE_OBLOCK_UNOCCUPIED, ItemType.OBLOCK,
324            rbxWarrant.getString("unoccupied"), rbxWarrant.getString("unoccupied")),
325        OBLOCK_OCCUPIED(TYPE_OBLOCK_OCCUPIED, ItemType.OBLOCK,
326            rbxWarrant.getString("occupied"), rbxWarrant.getString("occupied")),
327        OBLOCK_ALLOCATED(TYPE_OBLOCK_ALLOCATED, ItemType.OBLOCK,
328            rbxWarrant.getString("allocated"), rbxWarrant.getString("allocated")),
329        OBLOCK_RUNNING(TYPE_OBLOCK_RUNNING, ItemType.OBLOCK,
330            rbxWarrant.getString("running"), rbxWarrant.getString("running")),
331        OBLOCK_OUT_OF_SERVICE(TYPE_OBLOCK_OUT_OF_SERVICE, ItemType.OBLOCK,
332            rbxWarrant.getString("outOfService"), rbxWarrant.getString("outOfService")),
333        OBLOCK_DARK(TYPE_OBLOCK_DARK, ItemType.OBLOCK,
334            rbxWarrant.getString("dark"), rbxWarrant.getString("dark")),
335        OBLOCK_POWER_ERROR(TYPE_OBLOCK_POWER_ERROR, ItemType.OBLOCK,
336            rbxWarrant.getString("powerError"), rbxWarrant.getString("powerError")),
337        // This is used by ConditionalListEdit and ConditionalTreeEdit
338        XXXXXXX(TYPE_XXXXXXX, ItemType.NONE, "XXXXXXX", "XXXXXXX");
339
340        private final int _item;
341        private final ItemType _itemType;
342        private final String _string;
343        private final String _testTypeString;
344
345        private static final List<Type> sensorItemsList;
346        private static final List<Type> turnoutItemsList;
347        private static final List<Type> conditionalItemsList;
348        private static final List<Type> lightItemsList;
349        private static final List<Type> warrantItemsList;
350        private static final List<Type> memoryItemsList;
351        private static final List<Type> entryExitItemsList;
352        private static final List<Type> signalHeadStateMachineItemsList;
353        private static final List<Type> signalMastItemsList;
354        private static final List<Type> oblockItemsList;
355
356        private static final Set<Type> signalHeadAppearanceSet;
357
358
359        static
360        {
361            Type[] typeArray1 = {SENSOR_ACTIVE, SENSOR_INACTIVE};
362            sensorItemsList = Collections.unmodifiableList(Arrays.asList(typeArray1));
363
364            Type[] typeArray2 = {TURNOUT_THROWN, TURNOUT_CLOSED};
365            turnoutItemsList = Collections.unmodifiableList(Arrays.asList(typeArray2));
366
367            Type[] typeArray3 = {CONDITIONAL_TRUE, CONDITIONAL_FALSE};
368            conditionalItemsList = Collections.unmodifiableList(Arrays.asList(typeArray3));
369
370            Type[] typeArray4 = {LIGHT_ON, LIGHT_OFF};
371            lightItemsList = Collections.unmodifiableList(Arrays.asList(typeArray4));
372
373            Type[] typeArray5 = {ROUTE_FREE, ROUTE_SET, ROUTE_ALLOCATED, ROUTE_OCCUPIED, TRAIN_RUNNING};
374            warrantItemsList = Collections.unmodifiableList(Arrays.asList(typeArray5));
375
376            Type[] typeArray6 = {MEMORY_EQUALS, MEMORY_EQUALS_INSENSITIVE,
377                MEMORY_COMPARE, MEMORY_COMPARE_INSENSITIVE};
378            memoryItemsList = Collections.unmodifiableList(Arrays.asList(typeArray6));
379
380            Type[] typeArray7 = {ENTRYEXIT_ACTIVE, ENTRYEXIT_INACTIVE};
381            entryExitItemsList = Collections.unmodifiableList(Arrays.asList(typeArray7));
382
383            Type[] typeArray8 = {NONE, SIGNAL_HEAD_APPEARANCE_EQUALS, SIGNAL_HEAD_LIT, SIGNAL_HEAD_HELD};
384            signalHeadStateMachineItemsList = Collections.unmodifiableList(Arrays.asList(typeArray8));
385
386            Type[] typeArray9 = {SIGNAL_HEAD_RED, SIGNAL_HEAD_YELLOW, SIGNAL_HEAD_GREEN,
387                SIGNAL_HEAD_DARK, SIGNAL_HEAD_FLASHRED, SIGNAL_HEAD_FLASHYELLOW,
388                SIGNAL_HEAD_FLASHGREEN, SIGNAL_HEAD_LUNAR, SIGNAL_HEAD_FLASHLUNAR,
389            };
390            signalHeadAppearanceSet = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(typeArray9)));
391
392            Type[] typeArray10 = {NONE, SIGNAL_MAST_ASPECT_EQUALS, SIGNAL_MAST_LIT, SIGNAL_MAST_HELD};
393            signalMastItemsList = Collections.unmodifiableList(Arrays.asList(typeArray10));
394
395            Type[] typeArray11 = {OBLOCK_UNOCCUPIED, OBLOCK_OCCUPIED, OBLOCK_ALLOCATED,
396                OBLOCK_RUNNING, OBLOCK_OUT_OF_SERVICE, OBLOCK_DARK, OBLOCK_POWER_ERROR};
397            oblockItemsList = Collections.unmodifiableList(Arrays.asList(typeArray11));
398        }
399
400        Type(int state, ItemType itemType, String string, String testTypeString) {
401            _item = state;
402            _itemType = itemType;
403            _string = string;
404            _testTypeString = testTypeString;
405        }
406
407        public ItemType getItemType() {
408            return _itemType;
409        }
410
411        public int getIntValue() {
412            return _item;
413        }
414
415        public static List<Type> getSensorItems() {
416            return sensorItemsList;
417        }
418
419        public static List<Type> getTurnoutItems() {
420            return turnoutItemsList;
421        }
422
423        public static List<Type> getConditionalItems() {
424            return conditionalItemsList;
425        }
426
427        public static List<Type> getLightItems() {
428            return lightItemsList;
429        }
430
431        public static List<Type> getWarrantItems() {
432            return warrantItemsList;
433        }
434
435        public static List<Type> getMemoryItems() {
436            return memoryItemsList;
437        }
438
439        public static List<Type> getEntryExitItems() {
440            return entryExitItemsList;
441        }
442
443        public static List<Type> getSignalHeadStateMachineItems() {
444            return signalHeadStateMachineItemsList;
445        }
446
447        public static boolean isSignalHeadApperance(Type type) {
448            return signalHeadAppearanceSet.contains(type);
449        }
450
451        public static List<Type> getSignalMastItems() {
452            return signalMastItemsList;
453        }
454
455        public static List<Type> getOBlockItems() {
456            return oblockItemsList;
457        }
458
459        public static int getIndexInList(List<Type> table, Type entry) {
460            for (int i = 0; i < table.size(); i++) {
461                if (entry == table.get(i)) {
462                    return i;
463                }
464            }
465            return -1;
466        }
467
468        public static Type getOperatorFromIntValue(int typeInt) {
469            for (Type type : Type.values()) {
470                if (type.getIntValue() == typeInt) {
471                    return type;
472                }
473            }
474
475            throw new IllegalArgumentException("Type is unknown");
476        }
477
478        // Some items uses Bundle.getString() and some items uses rbx.getString()
479        // and therefore the items must call getString() in the call to the constructor.
480        @Override
481        public String toString() {
482            return _string;
483        }
484
485        public String getTestTypeString() {
486            return _testTypeString;
487        }
488    }
489
490    // items
491    enum Action {
492        NONE(ACTION_NONE, ItemType.NONE, ""), // NOI18N
493        SET_TURNOUT(ACTION_SET_TURNOUT, ItemType.TURNOUT,rbx.getString("ActionSetTurnout")),
494        // allowed settings for turnout are Thrown and Closed (in data)
495        SET_SIGNAL_APPEARANCE(ACTION_SET_SIGNAL_APPEARANCE, ItemType.SIGNALHEAD, rbx.getString("ActionSetSignal")),
496        // allowed settings for signal head are the seven Appearances (in data)
497        SET_SIGNAL_HELD(ACTION_SET_SIGNAL_HELD, ItemType.SIGNALHEAD, rbx.getString("ActionSetSignalHeld")),
498        CLEAR_SIGNAL_HELD(ACTION_CLEAR_SIGNAL_HELD, ItemType.SIGNALHEAD, rbx.getString("ActionClearSignalHeld")),
499        SET_SIGNAL_DARK(ACTION_SET_SIGNAL_DARK, ItemType.SIGNALHEAD, rbx.getString("ActionSetSignalDark")),
500        SET_SIGNAL_LIT(ACTION_SET_SIGNAL_LIT, ItemType.SIGNALHEAD, rbx.getString("ActionSetSignalLit")),
501        TRIGGER_ROUTE(ACTION_TRIGGER_ROUTE, ItemType.OTHER, rbx.getString("ActionTriggerRoute")),
502        SET_SENSOR(ACTION_SET_SENSOR, ItemType.SENSOR, rbx.getString("ActionSetSensor")),
503        // allowed settings for sensor are active and inactive (in data)
504        DELAYED_SENSOR(ACTION_DELAYED_SENSOR, ItemType.SENSOR, rbx.getString("ActionDelayedSensor")),
505        // allowed settings for timed sensor are active and inactive (in data)
506        //   time in seconds before setting sensor should be in delay
507        SET_LIGHT(ACTION_SET_LIGHT, ItemType.LIGHT, rbx.getString("ActionSetLight")),
508        // allowed settings for light are ON and OFF (in data)
509        SET_MEMORY(ACTION_SET_MEMORY, ItemType.MEMORY, rbx.getString("ActionSetMemory")),
510        // text to set into the memory variable should be in string
511        ENABLE_LOGIX(ACTION_ENABLE_LOGIX, ItemType.LOGIX, rbx.getString("ActionEnableLogix")),
512        DISABLE_LOGIX(ACTION_DISABLE_LOGIX, ItemType.LOGIX, rbx.getString("ActionDisableLogix")),
513        PLAY_SOUND(ACTION_PLAY_SOUND, ItemType.AUDIO, rbx.getString("ActionPlaySound")),
514        // reference to sound should be in string
515        RUN_SCRIPT(ACTION_RUN_SCRIPT, ItemType.SCRIPT, rbx.getString("ActionRunScript")),
516        // reference to script should be in string
517        DELAYED_TURNOUT(ACTION_DELAYED_TURNOUT, ItemType.TURNOUT, rbx.getString("ActionDelayedTurnout")),
518        // allowed settings for timed turnout are Thrown and Closed (in data)
519        //   time in seconds before setting turnout should be in delay
520        LOCK_TURNOUT(ACTION_LOCK_TURNOUT, ItemType.TURNOUT, rbx.getString("ActionTurnoutLock")),
521        RESET_DELAYED_SENSOR(ACTION_RESET_DELAYED_SENSOR, ItemType.SENSOR, rbx.getString("ActionResetDelayedSensor")),
522        // allowed settings for timed sensor are active and inactive (in data)
523        //   time in seconds before setting sensor should be in delay
524        CANCEL_SENSOR_TIMERS(ACTION_CANCEL_SENSOR_TIMERS, ItemType.SENSOR, rbx.getString("ActionCancelSensorTimers")),
525        // cancels all timers delaying setting of specified sensor
526        RESET_DELAYED_TURNOUT(ACTION_RESET_DELAYED_TURNOUT, ItemType.TURNOUT,
527            rbx.getString("ActionResetDelayedTurnout")),
528        // allowed settings for timed sensor are active and inactive (in data)
529        //   time in seconds before setting sensor should be in delay
530        CANCEL_TURNOUT_TIMERS(ACTION_CANCEL_TURNOUT_TIMERS, ItemType.TURNOUT,
531            rbx.getString("ActionCancelTurnoutTimers")),
532        // cancels all timers delaying setting of specified sensor
533        SET_FAST_CLOCK_TIME(ACTION_SET_FAST_CLOCK_TIME, ItemType.CLOCK, rbx.getString("ActionSetFastClockTime")),
534        // sets the fast clock time to the time specified
535        START_FAST_CLOCK(ACTION_START_FAST_CLOCK, ItemType.CLOCK, rbx.getString("ActionStartFastClock")),
536        // starts the fast clock
537        STOP_FAST_CLOCK(ACTION_STOP_FAST_CLOCK, ItemType.CLOCK, rbx.getString("ActionStopFastClock")),
538        // stops the fast clock
539        COPY_MEMORY(ACTION_COPY_MEMORY, ItemType.MEMORY, rbx.getString("ActionCopyMemory")),
540        // copies value from memory variable (in name) to memory variable (in string)
541        SET_LIGHT_INTENSITY(ACTION_SET_LIGHT_INTENSITY, ItemType.LIGHT, rbx.getString("ActionSetLightIntensity")),
542        SET_LIGHT_TRANSITION_TIME(ACTION_SET_LIGHT_TRANSITION_TIME, ItemType.LIGHT,
543            rbx.getString("ActionSetLightTransitionTime")),
544        // control the specified audio object
545        CONTROL_AUDIO(ACTION_CONTROL_AUDIO, ItemType.AUDIO, rbx.getString("ActionControlAudio")),
546        // execute a jython command
547        JYTHON_COMMAND(ACTION_JYTHON_COMMAND, ItemType.SCRIPT, rbx.getString("ActionJythonCommand")), // NOI18N
548        // Warrant actions
549        ALLOCATE_WARRANT_ROUTE(ACTION_ALLOCATE_WARRANT_ROUTE, ItemType.WARRANT, rbx.getString("ActionAllocateWarrant")),
550        DEALLOCATE_WARRANT_ROUTE(ACTION_DEALLOCATE_WARRANT_ROUTE, ItemType.WARRANT,
551            rbx.getString("ActionDeallocateWarrant")),
552        SET_ROUTE_TURNOUTS(ACTION_SET_ROUTE_TURNOUTS, ItemType.WARRANT, rbx.getString("ActionSetWarrantTurnouts")),
553        AUTO_RUN_WARRANT(ACTION_AUTO_RUN_WARRANT, ItemType.WARRANT, rbx.getString("ActionAutoRunWarrant")),
554        MANUAL_RUN_WARRANT(ACTION_MANUAL_RUN_WARRANT, ItemType.WARRANT, rbx.getString("ActionManualRunWarrant")),
555        CONTROL_TRAIN(ACTION_CONTROL_TRAIN, ItemType.WARRANT, rbx.getString("ActionControlTrain")),
556        SET_TRAIN_ID(ACTION_SET_TRAIN_ID, ItemType.WARRANT, rbx.getString("ActionSetTrainId")),
557        SET_TRAIN_NAME(ACTION_SET_TRAIN_NAME, ItemType.WARRANT, rbx.getString("ActionSetTrainName")),
558        SET_SIGNALMAST_ASPECT(ACTION_SET_SIGNALMAST_ASPECT, ItemType.SIGNALMAST,
559            rbx.getString("ActionSetSignalMastAspect")),
560        GET_TRAIN_LOCATION(ACTION_GET_TRAIN_LOCATION, ItemType.WARRANT, rbx.getString("ActionSetTrainLocation")),
561        GET_BLOCK_WARRANT(ACTION_GET_BLOCK_WARRANT, ItemType.OBLOCK, rbx.getString("ActionGetBlockWarrant")),
562        GET_BLOCK_TRAIN_NAME(ACTION_GET_BLOCK_TRAIN_NAME, ItemType.OBLOCK, rbx.getString("ActionGetBlockTrainName")),
563        SET_SIGNALMAST_HELD(ACTION_SET_SIGNALMAST_HELD, ItemType.SIGNALMAST, rbx.getString("ActionSetSignalMastHeld")),
564        CLEAR_SIGNALMAST_HELD(ACTION_CLEAR_SIGNALMAST_HELD, ItemType.SIGNALMAST,
565            rbx.getString("ActionClearSignalMastHeld")),
566        SET_SIGNALMAST_DARK(ACTION_SET_SIGNALMAST_DARK, ItemType.SIGNALMAST, rbx.getString("ActionSetSignalMastDark")),
567        SET_SIGNALMAST_LIT(ACTION_SET_SIGNALMAST_LIT, ItemType.SIGNALMAST, rbx.getString("ActionClearSignalMastDark")),
568        SET_BLOCK_VALUE(ACTION_SET_BLOCK_VALUE, ItemType.OBLOCK, rbx.getString("ActionSetBlockValue")),
569        SET_BLOCK_ERROR(ACTION_SET_BLOCK_ERROR, ItemType.OBLOCK, rbx.getString("ActionSetBlockError")),
570        CLEAR_BLOCK_ERROR(ACTION_CLEAR_BLOCK_ERROR, ItemType.OBLOCK, rbx.getString("ActionClearBlockError")),
571        DEALLOCATE_BLOCK(ACTION_DEALLOCATE_BLOCK, ItemType.OBLOCK, rbx.getString("ActionDeallocateBlock")),
572        SET_BLOCK_OUT_OF_SERVICE(ACTION_SET_BLOCK_OUT_OF_SERVICE, ItemType.OBLOCK,
573            rbx.getString("ActionSetBlockOutOfService")),
574        SET_BLOCK_IN_SERVICE(ACTION_SET_BLOCK_IN_SERVICE, ItemType.OBLOCK, rbx.getString("ActionBlockInService")),
575        // EntryExit Actions
576        SET_NXPAIR_ENABLED(ACTION_SET_NXPAIR_ENABLED, ItemType.ENTRYEXIT, rbx.getString("ActionNXPairEnabled")),
577        SET_NXPAIR_DISABLED(ACTION_SET_NXPAIR_DISABLED, ItemType.ENTRYEXIT, rbx.getString("ActionNXPairDisabled")),
578        SET_NXPAIR_SEGMENT(ACTION_SET_NXPAIR_SEGMENT, ItemType.ENTRYEXIT, rbx.getString("ActionNXPairSegment"));
579
580
581        private final int _item;
582        private final ItemType _itemType;
583        private final String _string;
584
585        private static final List<Action> sensorItemsList;
586        private static final List<Action> turnoutItemsList;
587        private static final List<Action> lightItemsList;
588        private static final List<Action> warrantItemsList;
589        private static final List<Action> memoryItemsList;
590        private static final List<Action> oblockItemsList;
591        private static final List<Action> entryExitItemsList;
592        private static final List<Action> signalHeadItemsList;
593        private static final List<Action> signalMastItemsList;
594        private static final List<Action> clockItemsList;
595        private static final List<Action> logixItemsList;
596        private static final List<Action> audioItemsList;
597        private static final List<Action> scriptItemsList;
598        private static final List<Action> otherItemsList;
599
600
601        static
602        {
603            Action[] typeArray1 = {SET_SENSOR, DELAYED_SENSOR,
604                RESET_DELAYED_SENSOR, CANCEL_SENSOR_TIMERS};
605            sensorItemsList = Collections.unmodifiableList(Arrays.asList(typeArray1));
606
607            Action[] typeArray2 = {SET_TURNOUT, DELAYED_TURNOUT, LOCK_TURNOUT,
608                CANCEL_TURNOUT_TIMERS, RESET_DELAYED_TURNOUT};
609            turnoutItemsList = Collections.unmodifiableList(Arrays.asList(typeArray2));
610
611            Action[] typeArray3 = {SET_LIGHT, SET_LIGHT_INTENSITY,
612                SET_LIGHT_TRANSITION_TIME};
613            lightItemsList = Collections.unmodifiableList(Arrays.asList(typeArray3));
614
615            Action[] typeArray4 = {ALLOCATE_WARRANT_ROUTE, DEALLOCATE_WARRANT_ROUTE,
616                SET_ROUTE_TURNOUTS, AUTO_RUN_WARRANT, MANUAL_RUN_WARRANT, CONTROL_TRAIN,
617                SET_TRAIN_ID, SET_TRAIN_NAME, GET_TRAIN_LOCATION};
618            warrantItemsList = Collections.unmodifiableList(Arrays.asList(typeArray4));
619
620            Action[] typeArray5 = {SET_MEMORY, COPY_MEMORY};
621            memoryItemsList = Collections.unmodifiableList(Arrays.asList(typeArray5));
622
623            Action[] typeArray6 = {SET_NXPAIR_ENABLED, SET_NXPAIR_DISABLED,
624                SET_NXPAIR_SEGMENT};
625            entryExitItemsList = Collections.unmodifiableList(Arrays.asList(typeArray6));
626
627            Action[] typeArray7 = {SET_SIGNAL_APPEARANCE, SET_SIGNAL_HELD,
628                CLEAR_SIGNAL_HELD, SET_SIGNAL_DARK, SET_SIGNAL_LIT};
629            signalHeadItemsList = Collections.unmodifiableList(Arrays.asList(typeArray7));
630
631            Action[] typeArray8 = {SET_SIGNALMAST_ASPECT, SET_SIGNALMAST_HELD,
632                CLEAR_SIGNALMAST_HELD, SET_SIGNALMAST_DARK, SET_SIGNALMAST_LIT};
633            signalMastItemsList = Collections.unmodifiableList(Arrays.asList(typeArray8));
634
635            Action[] typeArray9 = {SET_FAST_CLOCK_TIME, START_FAST_CLOCK,
636                STOP_FAST_CLOCK};
637            clockItemsList = Collections.unmodifiableList(Arrays.asList(typeArray9));
638
639            Action[] typeArray10 = {ENABLE_LOGIX, DISABLE_LOGIX};
640            logixItemsList = Collections.unmodifiableList(Arrays.asList(typeArray10));
641
642            Action[] typeArray11 = {DEALLOCATE_BLOCK, SET_BLOCK_VALUE,
643                SET_BLOCK_ERROR, CLEAR_BLOCK_ERROR, SET_BLOCK_OUT_OF_SERVICE,
644                SET_BLOCK_IN_SERVICE, GET_BLOCK_TRAIN_NAME, GET_BLOCK_WARRANT};
645            oblockItemsList = Collections.unmodifiableList(Arrays.asList(typeArray11));
646
647            Action[] typeArray12 = {PLAY_SOUND, CONTROL_AUDIO};
648            audioItemsList = Collections.unmodifiableList(Arrays.asList(typeArray12));
649
650            Action[] typeArray13 = {RUN_SCRIPT, JYTHON_COMMAND};
651            scriptItemsList = Collections.unmodifiableList(Arrays.asList(typeArray13));
652
653            Action[] typeArray14 = {TRIGGER_ROUTE};
654            otherItemsList = Collections.unmodifiableList(Arrays.asList(typeArray14));
655        }
656
657        Action(int state, ItemType itemType, String string) {
658            _item = state;
659            _itemType = itemType;
660            _string = string;
661        }
662
663        public ItemType getItemType() {
664            return _itemType;
665        }
666
667        public int getIntValue() {
668            return _item;
669        }
670
671        public static List<Action> getSensorItems() {
672            return sensorItemsList;
673        }
674
675        public static List<Action> getTurnoutItems() {
676            return turnoutItemsList;
677        }
678
679        public static List<Action> getLightItems() {
680            return lightItemsList;
681        }
682
683        public static List<Action> getWarrantItems() {
684            return warrantItemsList;
685        }
686
687        public static List<Action> getMemoryItems() {
688            return memoryItemsList;
689        }
690
691        public static List<Action> getOBlockItems() {
692            return oblockItemsList;
693        }
694
695        public static List<Action> getEntryExitItems() {
696            return entryExitItemsList;
697        }
698
699        public static List<Action> getSignalHeadItems() {
700            return signalHeadItemsList;
701        }
702
703        public static List<Action> getSignalMastItems() {
704            return signalMastItemsList;
705        }
706
707        public static List<Action> getClockItems() {
708            return clockItemsList;
709        }
710
711        public static List<Action> getLogixItems() {
712            return logixItemsList;
713        }
714
715        public static List<Action> getAudioItems() {
716            return audioItemsList;
717        }
718
719        public static List<Action> getScriptItems() {
720            return scriptItemsList;
721        }
722
723        public static List<Action> getOtherItems() {
724            return otherItemsList;
725        }
726
727        public static Action getOperatorFromIntValue(int actionInt) {
728            for (Action action : Action.values()) {
729                if (action.getIntValue() == actionInt) {
730                    return action;
731                }
732            }
733
734            throw new IllegalArgumentException("Action is unknown");
735        }
736
737        // Some items uses Bundle.getString() and some items uses rbx.getString()
738        // and therefore the items must call getString() in the call to the constructor.
739        @Override
740        public String toString() {
741            return _string;
742        }
743
744    }
745
746    // state variable types
747    int TYPE_ERROR = -1;
748    int TYPE_NONE = 0;
749    int TYPE_SENSOR_ACTIVE = 1;
750    int TYPE_SENSOR_INACTIVE = 2;
751    int TYPE_TURNOUT_THROWN = 3;
752    int TYPE_TURNOUT_CLOSED = 4;
753    int TYPE_CONDITIONAL_TRUE = 5;
754    int TYPE_CONDITIONAL_FALSE = 6;
755    int TYPE_LIGHT_ON = 7;
756    int TYPE_LIGHT_OFF = 8;
757    int TYPE_MEMORY_EQUALS = 9;
758    int TYPE_FAST_CLOCK_RANGE = 10;
759    // Note - within the TYPE_SIGNAL_HEAD definitions, all must be together,
760    //  RED must be first, and HELD must be last
761    int TYPE_SIGNAL_HEAD_RED = 11;
762    int TYPE_SIGNAL_HEAD_YELLOW = 12;
763    int TYPE_SIGNAL_HEAD_GREEN = 13;
764    int TYPE_SIGNAL_HEAD_DARK = 14;
765    int TYPE_SIGNAL_HEAD_FLASHRED = 15;
766    int TYPE_SIGNAL_HEAD_FLASHYELLOW = 16;
767    int TYPE_SIGNAL_HEAD_FLASHGREEN = 17;
768    int TYPE_SIGNAL_HEAD_LIT = 18;
769    int TYPE_SIGNAL_HEAD_HELD = 19;
770    int TYPE_MEMORY_COMPARE = 20;
771    int TYPE_SIGNAL_HEAD_LUNAR = 21;
772    int TYPE_SIGNAL_HEAD_FLASHLUNAR = 22;
773    int TYPE_MEMORY_EQUALS_INSENSITIVE = 23;
774    int TYPE_MEMORY_COMPARE_INSENSITIVE = 24;
775    // Warrant variables
776    int TYPE_ROUTE_FREE = 25;
777    int TYPE_ROUTE_OCCUPIED = 26;
778    int TYPE_ROUTE_ALLOCATED = 27;
779    int TYPE_ROUTE_SET = 28;
780    int TYPE_TRAIN_RUNNING = 29;
781    int TYPE_SIGNAL_MAST_ASPECT_EQUALS = 30;
782    int TYPE_SIGNAL_MAST_LIT = 31;
783    int TYPE_SIGNAL_MAST_HELD = 32;
784    int TYPE_SIGNAL_HEAD_APPEARANCE_EQUALS = 33;
785
786    int TYPE_BLOCK_STATUS_EQUALS = 34;
787
788    //Entry Exit Rules
789    int TYPE_ENTRYEXIT_ACTIVE = 35;
790    int TYPE_ENTRYEXIT_INACTIVE = 36;
791
792    int TYPE_OBLOCK_UNOCCUPIED = 37;
793    int TYPE_OBLOCK_OCCUPIED = 38;
794    int TYPE_OBLOCK_ALLOCATED = 39;
795    int TYPE_OBLOCK_RUNNING = 40;
796    int TYPE_OBLOCK_OUT_OF_SERVICE = 41;
797    int TYPE_OBLOCK_DARK = 42;
798    int TYPE_OBLOCK_POWER_ERROR = 43;
799
800    int TYPE_XXXXXXX = 9999;
801
802    // action definitions
803    int ACTION_OPTION_ON_CHANGE_TO_TRUE = 1;
804    int ACTION_OPTION_ON_CHANGE_TO_FALSE = 2;
805    int ACTION_OPTION_ON_CHANGE = 3;
806    int NUM_ACTION_OPTIONS = 3;
807
808    // action types
809    int ACTION_NONE = 1;
810    int ACTION_SET_TURNOUT = 2;
811    // allowed settings for turnout are Thrown and Closed (in data)
812    int ACTION_SET_SIGNAL_APPEARANCE = 3;
813    // allowed settings for signal head are the seven Appearances (in data)
814    int ACTION_SET_SIGNAL_HELD = 4;
815    int ACTION_CLEAR_SIGNAL_HELD = 5;
816    int ACTION_SET_SIGNAL_DARK = 6;
817    int ACTION_SET_SIGNAL_LIT = 7;
818    int ACTION_TRIGGER_ROUTE = 8;
819    int ACTION_SET_SENSOR = 9;
820    // allowed settings for sensor are active and inactive (in data)
821    int ACTION_DELAYED_SENSOR = 10;
822    // allowed settings for timed sensor are active and inactive (in data)
823    //   time in seconds before setting sensor should be in delay
824    int ACTION_SET_LIGHT = 11;
825    // allowed settings for light are ON and OFF (in data)
826    int ACTION_SET_MEMORY = 12;
827    // text to set into the memory variable should be in string
828    int ACTION_ENABLE_LOGIX = 13;
829    int ACTION_DISABLE_LOGIX = 14;
830    int ACTION_PLAY_SOUND = 15;
831    // reference to sound should be in string
832    int ACTION_RUN_SCRIPT = 16;
833    // reference to script should be in string
834    int ACTION_DELAYED_TURNOUT = 17;
835    // allowed settings for timed turnout are Thrown and Closed (in data)
836    //   time in seconds before setting turnout should be in delay
837    int ACTION_LOCK_TURNOUT = 18;
838    int ACTION_RESET_DELAYED_SENSOR = 19;
839    // allowed settings for timed sensor are active and inactive (in data)
840    //   time in seconds before setting sensor should be in delay
841    int ACTION_CANCEL_SENSOR_TIMERS = 20;
842    // cancels all timers delaying setting of specified sensor
843    int ACTION_RESET_DELAYED_TURNOUT = 21;
844    // allowed settings for timed sensor are active and inactive (in data)
845    //   time in seconds before setting sensor should be in delay
846    int ACTION_CANCEL_TURNOUT_TIMERS = 22;
847    // cancels all timers delaying setting of specified sensor
848    int ACTION_SET_FAST_CLOCK_TIME = 23;
849    // sets the fast clock time to the time specified
850    int ACTION_START_FAST_CLOCK = 24;
851    // starts the fast clock
852    int ACTION_STOP_FAST_CLOCK = 25;
853    // stops the fast clock
854    int ACTION_COPY_MEMORY = 26;
855    // copies value from memory variable (in name) to memory variable (in string)
856    int ACTION_SET_LIGHT_INTENSITY = 27;
857    int ACTION_SET_LIGHT_TRANSITION_TIME = 28;
858    // control the specified audio object
859    int ACTION_CONTROL_AUDIO = 29;
860    // execute a jython command
861    int ACTION_JYTHON_COMMAND = 30;
862    // Warrant actions
863    int ACTION_ALLOCATE_WARRANT_ROUTE = 31;
864    int ACTION_DEALLOCATE_WARRANT_ROUTE = 32;
865    int ACTION_SET_ROUTE_TURNOUTS = 33;
866    int ACTION_AUTO_RUN_WARRANT = 34;
867    int ACTION_CONTROL_TRAIN = 35;
868    int ACTION_SET_TRAIN_ID = 36;
869    int ACTION_SET_SIGNALMAST_ASPECT = 37;
870    int ACTION_GET_TRAIN_LOCATION = 38;
871    int ACTION_SET_SIGNALMAST_HELD = 39;
872    int ACTION_CLEAR_SIGNALMAST_HELD = 40;
873    int ACTION_SET_SIGNALMAST_DARK = 41;
874    int ACTION_SET_SIGNALMAST_LIT = 42;
875    int ACTION_SET_BLOCK_ERROR = 43;
876    int ACTION_CLEAR_BLOCK_ERROR = 44;
877    int ACTION_DEALLOCATE_BLOCK = 45;
878    int ACTION_SET_BLOCK_OUT_OF_SERVICE = 46;
879    int ACTION_SET_BLOCK_IN_SERVICE = 47;
880    int ACTION_MANUAL_RUN_WARRANT = 48;
881    int ACTION_SET_TRAIN_NAME = 49;
882    int ACTION_SET_BLOCK_VALUE = 50;
883    // EntryExit Actions
884    int ACTION_SET_NXPAIR_ENABLED = 51;
885    int ACTION_SET_NXPAIR_DISABLED = 52;
886    int ACTION_SET_NXPAIR_SEGMENT = 53;
887
888    int ACTION_GET_BLOCK_WARRANT = 54;
889    int ACTION_GET_BLOCK_TRAIN_NAME = 55;
890
891    /**
892     * ***********************************************************************************
893     */
894
895    /** New Variable and Action type scheme for Logix UI.
896     * State Variables and actions are grouped according to type.
897     * Variable and action types share the following group categories:
898     */
899    // state variable and action items used by logix.
900    int ITEM_TYPE_SENSOR = 1;
901    int ITEM_TYPE_TURNOUT = 2;
902    int ITEM_TYPE_LIGHT = 3;
903    int ITEM_TYPE_SIGNALHEAD = 4;
904    int ITEM_TYPE_SIGNALMAST = 5;
905    int ITEM_TYPE_MEMORY = 6;
906    int ITEM_TYPE_CONDITIONAL = 7;  // used only by ConditionalVariable
907    int ITEM_TYPE_LOGIX = 7;        // used only by ConditionalAction
908    int ITEM_TYPE_WARRANT = 8;
909    int ITEM_TYPE_CLOCK = 9;
910    int ITEM_TYPE_OBLOCK = 10;
911    int ITEM_TYPE_ENTRYEXIT = 11;
912
913    int ITEM_TYPE_AUDIO = 12;
914    int ITEM_TYPE_SCRIPT = 13;
915    int ITEM_TYPE_OTHER = 14;
916
917    /**
918     * set the logic type (all AND's all OR's or mixed AND's and OR's set the
919     * antecedent expression - should be a well formed boolean statement with
920     * parenthesis indicating the order of evaluation
921     *
922     * @param type       the type
923     * @param antecedent the expression
924     */
925    void setLogicType(Conditional.AntecedentOperator type, String antecedent);
926
927    /**
928     * Get antecedent (boolean expression) of Conditional
929     *
930     * @return the expression
931     */
932    String getAntecedentExpression();
933
934    /**
935     * Get type of operators in the antecedent statement
936     *
937     * @return the type
938     */
939    Conditional.AntecedentOperator getLogicType();
940
941    /**
942     * @return true if action list is executed only when state changes, false if
943     *         action list is executed on every calculation of state
944     */
945    boolean getTriggerOnChange();
946
947    /**
948     * Set policy for execution of action list
949     *
950     * @param trigger true execute only on change of state
951     */
952    void setTriggerOnChange(boolean trigger);
953
954    /**
955     * Set list of actions
956     *
957     * @param arrayList the actions
958     */
959    void setAction(@Nonnull List<ConditionalAction> arrayList);
960
961    /**
962     * Make deep clone of actions.
963     *
964     * @return a list of copies of actions
965     */
966    @Nonnull
967    List<ConditionalAction> getCopyOfActions();
968
969    /**
970     * Set State Variables for this Conditional. Each state variable will
971     * evaluate either True or False when this Conditional is calculated.
972     * <p>
973     * This method assumes that all information has been validated.
974     *
975     * @param arrayList the list of variables
976     */
977    void setStateVariables(@Nonnull List<ConditionalVariable> arrayList);
978
979    /**
980     * Make deep clone of variables.
981     *
982     * @return a list containing copies of variables
983     */
984    @Nonnull
985    List<ConditionalVariable> getCopyOfStateVariables();
986
987    /**
988     * Calculate this Conditional, triggering either or both actions if the user
989     * specified conditions are met, and the Logix is enabled. Sets the state of
990     * the conditional. Returns the calculated state of this Conditional.
991     *
992     * @param enabled true if Logix should be enabled; false otherwise
993     * @param evt     event to trigger if true
994     * @return the new state
995     */
996    int calculate(boolean enabled, PropertyChangeEvent evt);
997
998    /**
999     * Check that an antecedent is well formed.
1000     * If not, returns an error message.
1001     * Otherwise returns null.
1002     *
1003     * @param ant          the expression
1004     * @param variableList list of variables
1005     * @return true if well formed; false otherwise
1006     */
1007    @CheckForNull
1008    String validateAntecedent(@Nonnull String ant, List<ConditionalVariable> variableList);
1009
1010    /**
1011     * Stop a sensor timer if one is actively delaying setting of the specified
1012     * sensor
1013     *
1014     * @param sname the name of the timer
1015     */
1016    void cancelSensorTimer(String sname);
1017
1018    /**
1019     * Stop a turnout timer if one is actively delaying setting of the specified
1020     * turnout
1021     *
1022     * @param sname the name of the timer
1023     */
1024    void cancelTurnoutTimer(String sname);
1025
1026    /**
1027     * State of the Conditional is returned.
1028     *
1029     * @return state value
1030     */
1031    @Override
1032    int getState();
1033
1034    /**
1035     * Request a call-back when the bound KnownState property changes.
1036     *
1037     * @param l the listener
1038     */
1039    @Override
1040    void addPropertyChangeListener(PropertyChangeListener l);
1041
1042    /**
1043     * Remove a request for a call-back when a bound property changes.
1044     *
1045     * @param l the listener
1046     */
1047    @Override
1048    void removePropertyChangeListener(PropertyChangeListener l);
1049
1050    /**
1051     * Remove references to and from this object, so that it can eventually be
1052     * garbage-collected.
1053     */
1054    @Override
1055    void dispose();  // remove _all_ connections!
1056
1057}