001package jmri.jmrit.logixng.tools;
002
003import java.util.List;
004import java.util.concurrent.atomic.AtomicBoolean;
005
006import javax.annotation.Nonnull;
007
008import jmri.*;
009import jmri.implementation.DefaultConditionalAction;
010import jmri.jmrit.entryexit.DestinationPoints;
011import jmri.jmrit.logix.OBlock;
012import jmri.jmrit.logix.Warrant;
013import jmri.jmrit.logixng.*;
014import jmri.jmrit.logixng.actions.Logix;
015import jmri.jmrit.logixng.actions.*;
016import jmri.jmrit.logixng.expressions.*;
017import jmri.jmrit.logixng.util.TimerUnit;
018
019/**
020 * Imports Logixs to LogixNG
021 *
022 * @author Daniel Bergqvist 2019
023 */
024public class ImportConditional {
025
026    private final jmri.Conditional _conditional;
027    private final ConditionalNG _conditionalNG;
028    private final boolean _dryRun;
029
030
031    /**
032     * Create instance of ImportConditional
033     * @param logix         the parent Logix of the conditional to import
034     * @param conditional   the Conditional to import
035     * @param logixNG       the parent LogixNG that the new ConditionalNG will be added to
036     * @param sysName       the system name of the new ConditionalNG
037     * @param dryRun        true if import without creating any new beans,
038     *                      false if to create new beans
039     */
040    public ImportConditional(
041            jmri.Logix logix,
042            Conditional conditional,
043            LogixNG logixNG,
044            String sysName,
045            boolean dryRun) {
046
047        _dryRun = dryRun;
048        _conditional = conditional;
049        String userName = conditional.getSystemName();
050        if (conditional.getUserName() != null) {
051            userName += ": " + conditional.getUserName();
052        }
053
054        if (!_dryRun) {
055            ConditionalNG conditionalNG = null;
056            int counter = 0;
057            while ((conditionalNG == null) && counter < 100) {
058                String name = counter > 0 ? " - " + Integer.toString(counter) : "";
059                conditionalNG = InstanceManager.getDefault(jmri.jmrit.logixng.ConditionalNG_Manager.class)
060                        .createConditionalNG(logixNG, sysName, userName + name);
061                counter++;
062            }
063
064            if (conditionalNG == null) {
065                throw new RuntimeException("Cannot create new ConditionalNG with name: \"" + userName + "\"");
066            }
067
068            _conditionalNG = conditionalNG;
069        } else {
070            _conditionalNG = null;
071        }
072    }
073
074    public ConditionalNG getConditionalNG() {
075        return _conditionalNG;
076    }
077
078    public void doImport() throws SocketAlreadyConnectedException, JmriException {
079
080        Logix logix = new Logix(InstanceManager.getDefault(DigitalActionManager.class).getAutoSystemName(), null);
081
082        logix.setExecuteType(_conditional.getTriggerOnChange()
083                ? Logix.ExecuteType.ExecuteOnChange
084                : Logix.ExecuteType.ExecuteAlways);
085
086        Conditional.AntecedentOperator ao = _conditional.getLogicType();
087        String antecedentExpression = _conditional.getAntecedentExpression();
088        List<ConditionalVariable> conditionalVariables = _conditional.getCopyOfStateVariables();
089        List<ConditionalAction> conditionalActions = _conditional.getCopyOfActions();
090
091        DigitalExpressionBean expression;
092        switch (ao) {
093            case ALL_AND:
094                expression = new And(InstanceManager.getDefault(DigitalExpressionManager.class).getAutoSystemName(), null);
095                break;
096            case ALL_OR:
097                expression = new Or(InstanceManager.getDefault(DigitalExpressionManager.class).getAutoSystemName(), null);
098                break;
099            case MIXED:
100                expression = new Antecedent(InstanceManager.getDefault(DigitalExpressionManager.class).getAutoSystemName(), null);
101                ((Antecedent)expression).setAntecedent(antecedentExpression);
102                break;
103            default:
104                return;
105        }
106
107        // Is the Conditional a RTXINITIALIZER?
108        if ((conditionalVariables.size() == 1) && (conditionalVariables.get(0).getType().getItemType() == Conditional.ItemType.NONE)) {
109            expression =
110                    new TriggerOnce(InstanceManager.getDefault(DigitalExpressionManager.class)
111                            .getAutoSystemName(), null);
112
113            True trueExpression =
114                    new True(InstanceManager.getDefault(DigitalExpressionManager.class)
115                            .getAutoSystemName(), null);
116            if (!_dryRun) {
117                MaleSocket socket = InstanceManager.getDefault(DigitalExpressionManager.class)
118                        .registerExpression(trueExpression);
119                expression.getChild(0).connect(socket);
120            }
121        } else {
122            buildExpression(expression, conditionalVariables, ao != Conditional.AntecedentOperator.MIXED);
123        }
124
125        DigitalBooleanMany many =
126                new DigitalBooleanMany(InstanceManager.getDefault(
127                        DigitalBooleanActionManager.class).getAutoSystemName(), null);
128
129        buildAction(many, conditionalActions);
130
131        if (!_dryRun) {
132            MaleSocket expressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class).registerExpression(expression);
133            logix.getExpressionSocket().connect(expressionSocket);
134
135            MaleSocket manySocket = InstanceManager.getDefault(DigitalBooleanActionManager.class).registerAction(many);
136            logix.getActionSocket().connect(manySocket);
137
138            MaleSocket logixAction = InstanceManager.getDefault(DigitalActionManager.class).registerAction(logix);
139            _conditionalNG.getChild(0).connect(logixAction);
140        }
141    }
142
143
144    private void buildExpression(
145            DigitalExpressionBean expression,
146            List<ConditionalVariable> conditionalVariables,
147            boolean allowNot)
148            throws SocketAlreadyConnectedException, JmriException {
149
150        for (int i=0; i < conditionalVariables.size(); i++) {
151            jmri.ConditionalVariable cv = conditionalVariables.get(i);
152            NamedBean nb = cv.getBean();
153            AtomicBoolean isNegated = new AtomicBoolean(cv.isNegated() && allowNot);
154            DigitalExpressionBean newExpression;
155            switch (cv.getType().getItemType()) {
156                case SENSOR:
157                    Sensor sn = (Sensor)nb;
158                    newExpression = getSensorExpression(cv, sn, isNegated);
159                    break;
160                case TURNOUT:
161                    Turnout tn = (Turnout)nb;
162                    newExpression = getTurnoutExpression(cv, tn, isNegated);
163                    break;
164                case MEMORY:
165                    Memory my = (Memory)nb;
166                    newExpression = getMemoryExpression(cv, my);
167                    break;
168                case LIGHT:
169                    Light l = (Light)nb;
170                    newExpression = getLightExpression(cv, l, isNegated);
171                    break;
172                case SIGNALHEAD:
173                    SignalHead s = (SignalHead)nb;
174                    newExpression = getSignalHeadExpression(cv, s, isNegated);
175                    break;
176                case SIGNALMAST:
177                    SignalMast sm = (SignalMast)nb;
178                    newExpression = getSignalMastExpression(cv, sm, isNegated);
179                    break;
180                case ENTRYEXIT:
181                    DestinationPoints dp = (DestinationPoints)nb;
182                    newExpression = getEntryExitExpression(cv, dp, isNegated);
183                    break;
184                case CONDITIONAL:
185                    Conditional c = (Conditional)nb;
186                    newExpression = getConditionalExpression(cv, c, isNegated);
187                    break;
188                case CLOCK:
189                    newExpression = getFastClockExpression(cv, isNegated);
190                    break;
191                case WARRANT:
192                    Warrant w = (Warrant)nb;
193                    newExpression = getWarrantExpression(cv, w, isNegated);
194                    break;
195                case OBLOCK:
196                    OBlock b = (OBlock)nb;
197                    newExpression = getOBlockExpression(cv, b, isNegated);
198                    break;
199                default:
200                    newExpression = null;
201                    log.error("Unexpected type in ImportConditional.doImport(): {} -> {}", cv.getType().name(), cv.getType().getItemType().name());
202                    break;
203            }
204
205            if (newExpression != null) {
206
207                boolean doTriggerActions = cv.doTriggerActions();
208
209                if (isNegated.get()) {  // Some expressions have already handled Not
210                    Not notExpression = new Not(InstanceManager.getDefault(DigitalExpressionManager.class)
211                            .getAutoSystemName(), null);
212
213                    if (!_dryRun) {
214                        MaleSocket newExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class).registerExpression(newExpression);
215                        newExpressionSocket.setListen(doTriggerActions);
216                        doTriggerActions = true;    // We don't want the Not expression to disable listen.
217                        notExpression.getChild(0).connect(newExpressionSocket);
218                    }
219                    newExpression = notExpression;
220                }
221
222                if (!_dryRun) {
223                    MaleSocket newExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class).registerExpression(newExpression);
224                    newExpressionSocket.setListen(doTriggerActions);
225                    expression.getChild(i).connect(newExpressionSocket);
226                }
227            } else {
228                log.error("ImportConditional.doImport() did not created an expression for type: {} -> {}", cv.getType().name(), cv.getType().getItemType().name());
229            }
230        }
231    }
232
233
234    private void buildAction(DigitalBooleanMany many, List<ConditionalAction> conditionalActions)
235            throws SocketAlreadyConnectedException, JmriException {
236
237        for (int i=0; i < conditionalActions.size(); i++) {
238            ConditionalAction ca = conditionalActions.get(i);
239
240            DigitalBooleanLogixAction.When trigger;
241            switch (ca.getOption()) {
242                case Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE:
243                    trigger = DigitalBooleanLogixAction.When.True;
244                    break;
245
246                case Conditional.ACTION_OPTION_ON_CHANGE_TO_FALSE:
247                    trigger = DigitalBooleanLogixAction.When.False;
248                    break;
249
250                case Conditional.ACTION_OPTION_ON_CHANGE:
251                    trigger = DigitalBooleanLogixAction.When.Either;
252                    break;
253
254                default:
255                    throw new InvalidConditionalActionException(
256                            Bundle.getMessage("ActionBadTrigger", ca.getOption()));
257            }
258
259            DigitalBooleanActionBean booleanAction =
260                    new DigitalBooleanLogixAction(InstanceManager.getDefault(DigitalBooleanActionManager.class).getAutoSystemName(), null, trigger);
261
262            buildAction(booleanAction, ca);
263
264            if (!_dryRun) {
265                MaleSocket newBooleanActionSocket = InstanceManager.getDefault(DigitalBooleanActionManager.class).registerAction(booleanAction);
266                many.getChild(i).connect(newBooleanActionSocket);
267            }
268        }
269    }
270
271    private void buildAction(DigitalBooleanActionBean action, ConditionalAction conditionalAction)
272            throws SocketAlreadyConnectedException, JmriException {
273
274
275        String reference = null;
276        String devName = conditionalAction.getDeviceName();
277        if (devName != null && devName.length() > 0 && devName.charAt(0) == '@') {
278            reference = "{"+devName.substring(1)+"}";
279        }
280
281        NamedBean nb = conditionalAction.getBean();
282//        System.err.format("nb: %s%n", nb == null ? null : nb.getSystemName());
283        DigitalActionBean newAction;
284        switch (conditionalAction.getType().getItemType()) {
285            case SENSOR:
286                Sensor sn = (Sensor)nb;
287                newAction = getSensorAction(conditionalAction, sn, reference);
288                break;
289            case TURNOUT:
290                Turnout tn = (Turnout)nb;
291                newAction = getTurnoutAction(conditionalAction, tn, reference);
292                break;
293            case MEMORY:
294                Memory my = (Memory)nb;
295                newAction = getMemoryAction(conditionalAction, my, reference);
296                break;
297            case LIGHT:
298                Light l = (Light)nb;
299                newAction = getLightAction(conditionalAction, l, reference);
300                break;
301            case SIGNALHEAD:
302                SignalHead s = (SignalHead)nb;
303                newAction = getSignalHeadAction(conditionalAction, s, reference);
304                break;
305            case SIGNALMAST:
306                SignalMast sm = (SignalMast)nb;
307                newAction = getSignalMastAction(conditionalAction, sm, reference);
308                break;
309            case ENTRYEXIT:
310                DestinationPoints dp = (DestinationPoints)nb;
311                newAction = getEntryExitAction(conditionalAction, dp, reference);
312                break;
313            case WARRANT:
314                Warrant w = (Warrant)nb;
315                newAction = getWarrantAction(conditionalAction, w, reference);
316                break;
317            case OBLOCK:
318                OBlock b = (OBlock)nb;
319                newAction = getOBlockAction(conditionalAction, b, reference);
320                break;
321
322            case LOGIX:
323                newAction = getEnableLogixAction(conditionalAction);
324                break;
325
326            case CLOCK:
327                newAction = getClockAction(conditionalAction);
328                break;
329
330            case AUDIO:
331                newAction = getAudioOrSoundAction(conditionalAction);
332                break;
333
334            case SCRIPT:
335                newAction = getScriptAction(conditionalAction);
336                break;
337
338            case OTHER:
339                Route r = (Route) nb;
340                newAction = getRouteAction(conditionalAction, r, reference);
341                break;
342
343            default:
344                newAction = null;
345                log.warn("Unexpected type in ImportConditional.doImport(): {} -> {}", conditionalAction.getType(), conditionalAction.getType().getItemType());
346                break;
347        }
348
349        if (newAction != null) {
350            if (!_dryRun) {
351                MaleSocket newActionSocket = InstanceManager.getDefault(DigitalActionManager.class).registerAction(newAction);
352                action.getChild(0).connect(newActionSocket);
353            }
354        } else {
355            log.error("ImportConditional.doImport() did not created an action for type: {} -> {}", conditionalAction.getType(), conditionalAction.getType().getItemType());
356        }
357    }
358
359
360    private DigitalExpressionBean getSensorExpression(
361            @Nonnull ConditionalVariable cv,
362            Sensor sn,
363            AtomicBoolean isNegated)
364            throws JmriException {
365
366        ExpressionSensor expression =
367                new ExpressionSensor(InstanceManager.getDefault(DigitalExpressionManager.class)
368                        .getAutoSystemName(), null);
369
370//        System.err.format("Sensor: %s%n", sn == null ? null : sn.getSystemName());
371
372        expression.getSelectNamedBean().setNamedBean(sn);
373
374        if (isNegated.get()) {
375            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
376            isNegated.set(false);
377        }
378
379        switch (cv.getType()) {
380            case SENSOR_ACTIVE:
381                expression.getSelectEnum().setEnum(ExpressionSensor.SensorState.Active);
382                break;
383            case SENSOR_INACTIVE:
384                expression.getSelectEnum().setEnum(ExpressionSensor.SensorState.Inactive);
385                break;
386            default:
387                throw new InvalidConditionalVariableException(
388                        Bundle.getMessage("ConditionalBadSensorType", cv.getType().toString()));
389        }
390
391        return expression;
392    }
393
394
395    private DigitalExpressionBean getTurnoutExpression(
396            @Nonnull ConditionalVariable cv,
397            Turnout tn,
398            AtomicBoolean isNegated)
399            throws JmriException {
400
401        ExpressionTurnout expression =
402                new ExpressionTurnout(InstanceManager.getDefault(DigitalExpressionManager.class)
403                        .getAutoSystemName(), null);
404
405        expression.getSelectNamedBean().setNamedBean(tn);
406
407        if (isNegated.get()) {
408            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
409            isNegated.set(false);
410        }
411
412        switch (cv.getType()) {
413            case TURNOUT_CLOSED:
414                expression.setBeanState(ExpressionTurnout.TurnoutState.Closed);
415                break;
416            case TURNOUT_THROWN:
417                expression.setBeanState(ExpressionTurnout.TurnoutState.Thrown);
418                break;
419            default:
420                throw new InvalidConditionalVariableException(
421                        Bundle.getMessage("ConditionalBadTurnoutType", cv.getType().toString()));
422        }
423
424        return expression;
425    }
426
427
428    private DigitalExpressionBean getMemoryExpression(
429            @Nonnull ConditionalVariable cv, Memory my)
430            throws JmriException {
431
432        ExpressionMemory expression =
433                new ExpressionMemory(InstanceManager.getDefault(DigitalExpressionManager.class)
434                        .getAutoSystemName(), null);
435
436        expression.getSelectNamedBean().setNamedBean(my);
437
438        switch (cv.getNum1()) {
439            case ConditionalVariable.EQUAL:
440                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.Equal);
441                break;
442            case ConditionalVariable.LESS_THAN:
443                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.LessThan);
444                break;
445            case ConditionalVariable.LESS_THAN_OR_EQUAL:
446                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.LessThanOrEqual);
447                break;
448            case ConditionalVariable.GREATER_THAN:
449                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.GreaterThan);
450                break;
451            case ConditionalVariable.GREATER_THAN_OR_EQUAL:
452                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.GreaterThanOrEqual);
453                break;
454            default:
455                throw new InvalidConditionalVariableException(
456                        Bundle.getMessage("ConditionalBadMemoryNum1", cv.getType().toString()));
457        }
458
459        Memory memory;
460        switch (cv.getType()) {
461            case MEMORY_EQUALS:
462                expression.setCompareTo(ExpressionMemory.CompareTo.Value);
463                expression.setCaseInsensitive(false);
464                expression.setConstantValue(cv.getDataString());
465                break;
466            case MEMORY_EQUALS_INSENSITIVE:
467                expression.setCompareTo(ExpressionMemory.CompareTo.Value);
468                expression.setCaseInsensitive(true);
469                expression.setConstantValue(cv.getDataString());
470                break;
471            case MEMORY_COMPARE:
472                expression.setCompareTo(ExpressionMemory.CompareTo.Memory);
473                expression.setCaseInsensitive(false);
474                expression.getSelectOtherMemoryNamedBean().setNamedBean(cv.getDataString());
475                memory = InstanceManager.getDefault(MemoryManager.class).getMemory(cv.getDataString());
476                if (memory == null) {   // Logix allows the memory name in cv.getDataString() to be a system name without system prefix
477                    memory = InstanceManager.getDefault(MemoryManager.class).provide(cv.getDataString());
478                    expression.getSelectOtherMemoryNamedBean().setNamedBean(memory.getSystemName());
479                }
480                break;
481            case MEMORY_COMPARE_INSENSITIVE:
482                expression.setCompareTo(ExpressionMemory.CompareTo.Memory);
483                expression.setCaseInsensitive(true);
484                expression.getSelectOtherMemoryNamedBean().setNamedBean(cv.getDataString());
485                memory = InstanceManager.getDefault(MemoryManager.class).getMemory(cv.getDataString());
486                if (memory == null) {   // Logix allows the memory name in cv.getDataString() to be a system name without system prefix
487                    memory = InstanceManager.getDefault(MemoryManager.class).provide(cv.getDataString());
488                    expression.getSelectOtherMemoryNamedBean().setNamedBean(memory.getSystemName());
489                }
490                break;
491            default:
492                throw new InvalidConditionalVariableException(
493                        Bundle.getMessage("ConditionalBadMemoryType", cv.getType().toString()));
494        }
495
496        expression.setListenToOtherMemory(false);
497
498        return expression;
499    }
500
501
502    private DigitalExpressionBean getLightExpression(
503            @Nonnull ConditionalVariable cv,
504            Light ln,
505            AtomicBoolean isNegated)
506            throws JmriException {
507
508        ExpressionLight expression =
509                new ExpressionLight(InstanceManager.getDefault(DigitalExpressionManager.class)
510                        .getAutoSystemName(), null);
511
512        expression.getSelectNamedBean().setNamedBean(ln);
513
514        if (isNegated.get()) {
515            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
516            isNegated.set(false);
517        }
518
519        switch (cv.getType()) {
520            case LIGHT_ON:
521                expression.setBeanState(ExpressionLight.LightState.On);
522                break;
523            case LIGHT_OFF:
524                expression.setBeanState(ExpressionLight.LightState.Off);
525                break;
526            default:
527                throw new InvalidConditionalVariableException(
528                        Bundle.getMessage("ConditionalBadLightType", cv.getType().toString()));
529        }
530
531        return expression;
532    }
533
534
535    private DigitalExpressionBean getSignalHeadExpression(
536            @Nonnull ConditionalVariable cv,
537            SignalHead s,
538            AtomicBoolean isNegated)
539            throws JmriException {
540
541        ExpressionSignalHead expression =
542                new ExpressionSignalHead(InstanceManager.getDefault(DigitalExpressionManager.class)
543                        .getAutoSystemName(), null);
544
545        expression.getSelectNamedBean().setNamedBean(s);
546
547        ExpressionSignalHead.QueryType appearence =
548                isNegated.get() ? ExpressionSignalHead.QueryType.NotAppearance
549                : ExpressionSignalHead.QueryType.Appearance;
550
551        switch (cv.getType()) {
552            case SIGNAL_HEAD_RED:
553                expression.setQueryType(appearence);
554                expression.setAppearance(SignalHead.RED);
555                break;
556            case SIGNAL_HEAD_YELLOW:
557                expression.setQueryType(appearence);
558                expression.setAppearance(SignalHead.YELLOW);
559                break;
560            case SIGNAL_HEAD_GREEN:
561                expression.setQueryType(appearence);
562                expression.setAppearance(SignalHead.GREEN);
563                break;
564            case SIGNAL_HEAD_DARK:
565                expression.setQueryType(appearence);
566                expression.setAppearance(SignalHead.DARK);
567                break;
568            case SIGNAL_HEAD_FLASHRED:
569                expression.setQueryType(appearence);
570                expression.setAppearance(SignalHead.FLASHRED);
571                break;
572            case SIGNAL_HEAD_FLASHYELLOW:
573                expression.setQueryType(appearence);
574                expression.setAppearance(SignalHead.FLASHYELLOW);
575                break;
576            case SIGNAL_HEAD_FLASHGREEN:
577                expression.setQueryType(appearence);
578                expression.setAppearance(SignalHead.FLASHGREEN);
579                break;
580            case SIGNAL_HEAD_LUNAR:
581                expression.setQueryType(appearence);
582                expression.setAppearance(SignalHead.LUNAR);
583                break;
584            case SIGNAL_HEAD_FLASHLUNAR:
585                expression.setQueryType(appearence);
586                expression.setAppearance(SignalHead.FLASHLUNAR);
587                break;
588            case SIGNAL_HEAD_LIT:
589                expression.setQueryType(isNegated.get() ? ExpressionSignalHead.QueryType.NotLit : ExpressionSignalHead.QueryType.Lit);
590                break;
591            case SIGNAL_HEAD_HELD:
592                expression.setQueryType(isNegated.get() ? ExpressionSignalHead.QueryType.NotHeld : ExpressionSignalHead.QueryType.Held);
593                break;
594            default:
595                throw new InvalidConditionalVariableException(
596                        Bundle.getMessage("ConditionalBadSignalHeadType", cv.getType().toString()));
597        }
598
599        isNegated.set(false);   // We have already handled this
600
601        return expression;
602    }
603
604
605    private DigitalExpressionBean getSignalMastExpression(
606            @Nonnull ConditionalVariable cv,
607            SignalMast sm,
608            AtomicBoolean isNegated)
609            throws JmriException {
610
611        ExpressionSignalMast expression =
612                new ExpressionSignalMast(InstanceManager.getDefault(DigitalExpressionManager.class)
613                        .getAutoSystemName(), null);
614
615        expression.getSelectNamedBean().setNamedBean(sm);
616
617        ExpressionSignalMast.QueryType aspect =
618                isNegated.get() ? ExpressionSignalMast.QueryType.NotAspect
619                : ExpressionSignalMast.QueryType.Aspect;
620
621        switch (cv.getType()) {
622            case SIGNAL_MAST_ASPECT_EQUALS:
623                expression.setQueryType(aspect);
624                expression.setAspect(cv.getDataString());
625                break;
626            case SIGNAL_MAST_LIT:
627                expression.setQueryType(isNegated.get() ? ExpressionSignalMast.QueryType.NotLit : ExpressionSignalMast.QueryType.Lit);
628                break;
629            case SIGNAL_MAST_HELD:
630                expression.setQueryType(isNegated.get() ? ExpressionSignalMast.QueryType.NotHeld : ExpressionSignalMast.QueryType.Held);
631                break;
632            default:
633                throw new InvalidConditionalVariableException(
634                        Bundle.getMessage("ConditionalBadSignalMastType", cv.getType().toString()));
635        }
636
637        isNegated.set(false);   // We have already handled this
638
639        return expression;
640    }
641
642
643    private DigitalExpressionBean getEntryExitExpression(
644            @Nonnull ConditionalVariable cv,
645            DestinationPoints dp,
646            AtomicBoolean isNegated)
647            throws JmriException {
648
649        ExpressionEntryExit expression =
650                new ExpressionEntryExit(InstanceManager.getDefault(DigitalExpressionManager.class)
651                        .getAutoSystemName(), null);
652
653        expression.getSelectNamedBean().setNamedBean(dp);
654
655        if (isNegated.get()) {
656            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
657            isNegated.set(false);
658        }
659
660        switch (cv.getType()) {
661            case ENTRYEXIT_ACTIVE:
662                expression.setBeanState(ExpressionEntryExit.EntryExitState.Active);
663                break;
664            case ENTRYEXIT_INACTIVE:
665                expression.setBeanState(ExpressionEntryExit.EntryExitState.Inactive);
666                break;
667            default:
668                throw new InvalidConditionalVariableException(
669                        Bundle.getMessage("ConditionalBadEntryExitType", cv.getType().toString()));
670        }
671
672        return expression;
673    }
674
675
676    private DigitalExpressionBean getConditionalExpression(
677            @Nonnull ConditionalVariable cv,
678            Conditional cn,
679            AtomicBoolean isNegated)
680            throws JmriException {
681
682        ExpressionConditional expression =
683                new ExpressionConditional(InstanceManager.getDefault(DigitalExpressionManager.class)
684                        .getAutoSystemName(), null);
685
686        expression.getSelectNamedBean().setNamedBean(cn);
687
688        if (isNegated.get()) {
689            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
690            isNegated.set(false);
691        }
692
693        switch (cv.getType()) {
694            case CONDITIONAL_TRUE:
695                expression.setConditionalState(ExpressionConditional.ConditionalState.True);
696                break;
697            case CONDITIONAL_FALSE:
698                expression.setConditionalState(ExpressionConditional.ConditionalState.False);
699                break;
700            default:
701                throw new InvalidConditionalVariableException(
702                        Bundle.getMessage("ConditionalBadConditionalType", cv.getType().toString()));
703        }
704
705        return expression;
706    }
707
708
709    private DigitalExpressionBean getFastClockExpression(
710            @Nonnull ConditionalVariable cv,
711            AtomicBoolean isNegated)
712            throws JmriException {
713
714        ExpressionClock expression =
715                new ExpressionClock(InstanceManager.getDefault(DigitalExpressionManager.class)
716                        .getAutoSystemName(), null);
717
718        if (isNegated.get()) {
719            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
720            isNegated.set(false);
721        }
722
723        if (cv.getType() != Conditional.Type.FAST_CLOCK_RANGE) {
724            throw new InvalidConditionalVariableException(
725                    Bundle.getMessage("ConditionalBadFastClockType", cv.getType().toString()));
726        }
727                log.info("Found a clock range");
728
729        expression.setType(ExpressionClock.Type.FastClock);
730        expression.setRange(ConditionalVariable.fixMidnight(cv.getNum1()), ConditionalVariable.fixMidnight(cv.getNum2()));
731
732        return expression;
733    }
734
735
736    private DigitalExpressionBean getWarrantExpression(
737            @Nonnull ConditionalVariable cv,
738            Warrant w,
739            AtomicBoolean isNegated)
740            throws JmriException {
741
742        ExpressionWarrant expression =
743                new ExpressionWarrant(InstanceManager.getDefault(DigitalExpressionManager.class)
744                        .getAutoSystemName(), null);
745
746        expression.getSelectNamedBean().setNamedBean(w);
747
748        if (isNegated.get()) {
749            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
750            isNegated.set(false);
751        }
752
753        switch (cv.getType()) {
754            case ROUTE_FREE:
755                expression.setBeanState(ExpressionWarrant.WarrantState.RouteFree);
756                break;
757            case ROUTE_OCCUPIED:
758                expression.setBeanState(ExpressionWarrant.WarrantState.RouteOccupied);
759                break;
760            case ROUTE_ALLOCATED:
761                expression.setBeanState(ExpressionWarrant.WarrantState.RouteAllocated);
762                break;
763            case ROUTE_SET:
764                expression.setBeanState(ExpressionWarrant.WarrantState.RouteSet);
765                break;
766            case TRAIN_RUNNING:
767                expression.setBeanState(ExpressionWarrant.WarrantState.TrainRunning);
768                break;
769            default:
770                throw new InvalidConditionalVariableException(
771                        Bundle.getMessage("ConditionalBadWarrantType", cv.getType().toString()));
772        }
773
774        return expression;
775    }
776
777
778    private DigitalExpressionBean getOBlockExpression(
779            @Nonnull ConditionalVariable cv,
780            OBlock b,
781            AtomicBoolean isNegated)
782            throws JmriException {
783
784        ExpressionOBlock expression =
785                new ExpressionOBlock(InstanceManager.getDefault(DigitalExpressionManager.class)
786                        .getAutoSystemName(), null);
787
788        if (isNegated.get()) {
789            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
790            isNegated.set(false);
791        }
792
793        OBlock.OBlockStatus oblockStatus = OBlock.OBlockStatus.getByName(cv.getDataString());
794
795        if (oblockStatus == null) {
796            throw new InvalidConditionalVariableException(
797                    Bundle.getMessage("ConditionalBadOBlockDataString", cv.getDataString()));
798        }
799
800        expression.getSelectNamedBean().setNamedBean(b);
801        expression.setBeanState(oblockStatus);
802
803        return expression;
804    }
805
806
807    private DigitalActionBean getSensorAction(@Nonnull ConditionalAction ca, Sensor sn, String reference) throws JmriException {
808
809        switch (ca.getType()) {
810            case SET_SENSOR:
811                ActionSensor action =
812                        new ActionSensor(InstanceManager.getDefault(DigitalActionManager.class)
813                                .getAutoSystemName(), null);
814
815                if (reference != null) {
816                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
817                    action.getSelectNamedBean().setReference(reference);
818                } else {
819                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
820                    action.getSelectNamedBean().setNamedBean(sn);
821                }
822
823                switch (ca.getActionData()) {
824                    case jmri.Route.TOGGLE:
825                        action.getSelectEnum().setEnum(ActionSensor.SensorState.Toggle);
826                        break;
827
828                    case Sensor.INACTIVE:
829                        action.getSelectEnum().setEnum(ActionSensor.SensorState.Inactive);
830                        break;
831
832                    case Sensor.ACTIVE:
833                        action.getSelectEnum().setEnum(ActionSensor.SensorState.Active);
834                        break;
835
836                    default:
837                        throw new InvalidConditionalVariableException(
838                                Bundle.getMessage("ActionBadSensorState", ca.getActionData()));
839                }
840                return action;
841
842            case RESET_DELAYED_SENSOR:
843            case DELAYED_SENSOR:
844                ConditionalAction caTemp = new DefaultConditionalAction();
845                caTemp.setType(Conditional.Action.SET_SENSOR);
846                caTemp.setActionData(ca.getActionData());
847                DigitalActionBean subAction = getSensorAction(caTemp, sn, reference);
848                ExecuteDelayed delayedAction =
849                        new ExecuteDelayed(InstanceManager.getDefault(DigitalActionManager.class)
850                                .getAutoSystemName(), null);
851
852                String sNumber = ca.getActionString();
853                try {
854                    int time = Integer.parseInt(sNumber);
855                    delayedAction.setDelay(time);
856                    delayedAction.setUnit(TimerUnit.Seconds);
857                } catch (NumberFormatException e) {
858                    try {
859                        float time = Float.parseFloat(sNumber);
860                        delayedAction.setDelay((int) (time * 1000));
861                        delayedAction.setUnit(TimerUnit.MilliSeconds);
862                    } catch (NumberFormatException e2) {
863                        // If here, assume that sNumber has the name of a memory.
864                        // Logix supports this memory to have a floating point value
865                        // but LogixNG requires this memory to have an integer value.
866                        if (sNumber.charAt(0) == '@') {
867                            sNumber = sNumber.substring(1);
868                        }
869                        delayedAction.setDelayAddressing(NamedBeanAddressing.Reference);
870                        delayedAction.setDelayReference("{" + sNumber + "}");
871                        delayedAction.setUnit(TimerUnit.Seconds);
872                    }
873                }
874
875                delayedAction.setResetIfAlreadyStarted(ca.getType() == Conditional.Action.RESET_DELAYED_SENSOR);
876                if (!_dryRun) {
877                    MaleSocket subActionSocket = InstanceManager.getDefault(DigitalActionManager.class)
878                            .registerAction(subAction);
879                    delayedAction.getChild(0).connect(subActionSocket);
880                }
881                return delayedAction;
882
883            case CANCEL_SENSOR_TIMERS:
884            default:
885                throw new InvalidConditionalVariableException(
886                        Bundle.getMessage("ActionBadSensorType", ca.getType().toString()));
887        }
888    }
889
890
891    private DigitalActionBean getTurnoutAction(@Nonnull ConditionalAction ca, Turnout tn, String reference) throws JmriException {
892
893        ActionTurnout action;
894
895        switch (ca.getType()) {
896            case SET_TURNOUT:
897                action = new ActionTurnout(InstanceManager.getDefault(DigitalActionManager.class)
898                                .getAutoSystemName(), null);
899
900                if (reference != null) {
901                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
902                    action.getSelectNamedBean().setReference(reference);
903                } else {
904                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
905                    action.getSelectNamedBean().setNamedBean(tn);
906                }
907
908                switch (ca.getActionData()) {
909                    case jmri.Route.TOGGLE:
910                        action.getSelectEnum().setEnum(ActionTurnout.TurnoutState.Toggle);
911                        break;
912
913                    case Turnout.CLOSED:
914                        action.getSelectEnum().setEnum(ActionTurnout.TurnoutState.Closed);
915                        break;
916
917                    case Turnout.THROWN:
918                        action.getSelectEnum().setEnum(ActionTurnout.TurnoutState.Thrown);
919                        break;
920
921                    default:
922                        throw new InvalidConditionalVariableException(
923                                Bundle.getMessage("ActionBadTurnoutState", ca.getActionData()));
924                }
925                break;
926
927            case RESET_DELAYED_TURNOUT:
928            case DELAYED_TURNOUT:
929                ConditionalAction caTemp = new DefaultConditionalAction();
930                caTemp.setType(Conditional.Action.SET_TURNOUT);
931                caTemp.setActionData(ca.getActionData());
932                DigitalActionBean subAction = getTurnoutAction(caTemp, tn, reference);
933                ExecuteDelayed delayedAction =
934                        new ExecuteDelayed(InstanceManager.getDefault(DigitalActionManager.class)
935                                .getAutoSystemName(), null);
936
937                String sNumber = ca.getActionString();
938                try {
939                    int time = Integer.parseInt(sNumber);
940                    delayedAction.setDelay(time);
941                    delayedAction.setUnit(TimerUnit.Seconds);
942                } catch (NumberFormatException e) {
943                    try {
944                        float time = Float.parseFloat(sNumber);
945                        delayedAction.setDelay((int) (time * 1000));
946                        delayedAction.setUnit(TimerUnit.MilliSeconds);
947                    } catch (NumberFormatException e2) {
948                        // If here, assume that sNumber has the name of a memory.
949                        // Logix supports this memory to have a floating point value
950                        // but LogixNG requires this memory to have an integer value.
951                        if (sNumber.charAt(0) == '@') {
952                            sNumber = sNumber.substring(1);
953                        }
954                        delayedAction.setDelayAddressing(NamedBeanAddressing.Reference);
955                        delayedAction.setDelayReference("{" + sNumber + "}");
956                        delayedAction.setUnit(TimerUnit.Seconds);
957                    }
958                }
959
960                delayedAction.setResetIfAlreadyStarted(ca.getType() == Conditional.Action.RESET_DELAYED_TURNOUT);
961                if (!_dryRun) {
962                    MaleSocket subActionSocket = InstanceManager.getDefault(DigitalActionManager.class)
963                            .registerAction(subAction);
964                    delayedAction.getChild(0).connect(subActionSocket);
965                }
966                return delayedAction;
967
968            case LOCK_TURNOUT:
969                ActionTurnoutLock action2 = new ActionTurnoutLock(InstanceManager.getDefault(DigitalActionManager.class)
970                                .getAutoSystemName(), null);
971
972                if (reference != null) {
973                    action2.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
974                    action2.getSelectNamedBean().setReference(reference);
975                } else {
976                    action2.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
977                    action2.getSelectNamedBean().setNamedBean(tn);
978                }
979
980                switch (ca.getActionData()) {
981                    case jmri.Route.TOGGLE:
982                        action2.getSelectEnum().setEnum(ActionTurnoutLock.TurnoutLock.Toggle);
983                        break;
984
985                    case Turnout.LOCKED:
986                        action2.getSelectEnum().setEnum(ActionTurnoutLock.TurnoutLock.Lock);
987                        break;
988
989                    case Turnout.UNLOCKED:
990                        action2.getSelectEnum().setEnum(ActionTurnoutLock.TurnoutLock.Unlock);
991                        break;
992
993                    default:
994                        throw new InvalidConditionalVariableException(
995                                Bundle.getMessage("ActionBadTurnoutLock", ca.getActionData()));
996                }
997                return action2;
998
999            case CANCEL_TURNOUT_TIMERS:
1000            default:
1001                throw new InvalidConditionalVariableException(
1002                        Bundle.getMessage("ActionBadTurnoutType", ca.getType().toString()));
1003        }
1004
1005        return action;
1006    }
1007
1008
1009    private DigitalActionBean getMemoryAction(@Nonnull ConditionalAction ca, Memory my, String reference) throws JmriException {
1010
1011        ActionMemory action;
1012
1013        action = new ActionMemory(InstanceManager.getDefault(DigitalActionManager.class)
1014                        .getAutoSystemName(), null);
1015
1016        if (reference != null) {
1017            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1018            action.getSelectNamedBean().setReference(reference);
1019        } else {
1020            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1021            action.getSelectNamedBean().setNamedBean(my);
1022        }
1023
1024        switch (ca.getType()) {
1025            case SET_MEMORY:
1026                action.setMemoryOperation(ActionMemory.MemoryOperation.SetToString);
1027                action.setOtherConstantValue(ca.getActionString());
1028                break;
1029
1030            case COPY_MEMORY:
1031                action.setMemoryOperation(ActionMemory.MemoryOperation.CopyMemoryToMemory);
1032
1033                // Logix COPY_MEMORY stores data reversed
1034                String fromMemory = ca.getActionString();
1035                if ((!fromMemory.isEmpty()) && fromMemory.charAt(0) == '@') {
1036                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1037                    action.getSelectNamedBean().setReference("{"+fromMemory.substring(1)+"}");
1038                } else {
1039                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1040                    action.getSelectNamedBean().setNamedBean(fromMemory);
1041                }
1042
1043                if (reference != null) {
1044                    action.getSelectOtherMemoryNamedBean().setAddressing(NamedBeanAddressing.Reference);
1045                    action.getSelectOtherMemoryNamedBean().setReference(reference);
1046                } else {
1047                    action.getSelectOtherMemoryNamedBean().setAddressing(NamedBeanAddressing.Direct);
1048                    action.getSelectOtherMemoryNamedBean().setNamedBean(my);
1049                }
1050
1051                break;
1052
1053            default:
1054                throw new InvalidConditionalVariableException(
1055                        Bundle.getMessage("ActionBadMemoryType", ca.getActionData()));
1056        }
1057
1058        return action;
1059    }
1060
1061
1062    private DigitalActionBean getLightAction(@Nonnull ConditionalAction ca, Light l, String reference) throws JmriException {
1063
1064        ActionLight action = new ActionLight(InstanceManager.getDefault(DigitalActionManager.class)
1065                .getAutoSystemName(), null);
1066
1067        if (reference != null) {
1068            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1069            action.getSelectNamedBean().setReference(reference);
1070        } else {
1071            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1072            action.getSelectNamedBean().setNamedBean(l);
1073        }
1074
1075        switch (ca.getType()) {
1076            case SET_LIGHT:
1077                switch (ca.getActionData()) {
1078                    case jmri.Route.TOGGLE:
1079                        action.getSelectEnum().setEnum(ActionLight.LightState.Toggle);
1080                        break;
1081
1082                    case Light.OFF:
1083                        action.getSelectEnum().setEnum(ActionLight.LightState.Off);
1084                        break;
1085
1086                    case Light.ON:
1087                        action.getSelectEnum().setEnum(ActionLight.LightState.On);
1088                        break;
1089
1090                    default:
1091                        throw new InvalidConditionalVariableException(
1092                                Bundle.getMessage("ActionBadLightState", ca.getActionData()));
1093                }
1094                break;
1095
1096            case SET_LIGHT_INTENSITY:
1097                int intensity;
1098                try {
1099                    intensity = Integer.parseInt(ca.getActionString());
1100                    if (intensity < 0 || intensity > 100) {
1101                        intensity = 0;
1102                    }
1103                } catch (NumberFormatException ex) {
1104                    intensity = 0;
1105                }
1106                action.setLightValue(intensity);
1107                action.getSelectEnum().setEnum(ActionLight.LightState.Intensity);
1108                break;
1109
1110            case SET_LIGHT_TRANSITION_TIME:
1111                int interval;
1112                try {
1113                    interval = Integer.parseInt(ca.getActionString());
1114                    if (interval < 0) {
1115                        interval = 0;
1116                    }
1117                } catch (NumberFormatException ex) {
1118                    interval = 0;
1119                }
1120                action.setLightValue(interval);
1121                action.getSelectEnum().setEnum(ActionLight.LightState.Interval);
1122                break;
1123
1124            default:
1125                throw new InvalidConditionalVariableException(
1126                        Bundle.getMessage("ActionBadLightType", ca.getType().toString()));
1127        }
1128
1129        return action;
1130    }
1131
1132
1133    private DigitalActionBean getSignalHeadAction(@Nonnull ConditionalAction ca, SignalHead sh, String reference) throws JmriException {
1134        ActionSignalHead action =
1135                new ActionSignalHead(InstanceManager.getDefault(DigitalActionManager.class)
1136                        .getAutoSystemName(), null);
1137
1138        if (reference != null) {
1139            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1140            action.getSelectNamedBean().setReference(reference);
1141        } else {
1142            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1143            action.getSelectNamedBean().setNamedBean(sh);
1144        }
1145        action.setOperationAddressing(NamedBeanAddressing.Direct);
1146        action.setAppearanceAddressing(NamedBeanAddressing.Direct);
1147
1148        action.getSelectNamedBean().setNamedBean(sh);
1149
1150        switch (ca.getType()) {
1151            case SET_SIGNAL_APPEARANCE:
1152                action.setOperationType(ActionSignalHead.OperationType.Appearance);
1153                action.setAppearance(ca.getActionData());
1154                break;
1155
1156            case SET_SIGNAL_HELD:
1157                action.setOperationType(ActionSignalHead.OperationType.Held);
1158                break;
1159
1160            case CLEAR_SIGNAL_HELD:
1161                action.setOperationType(ActionSignalHead.OperationType.NotHeld);
1162                break;
1163
1164            case SET_SIGNAL_LIT:
1165                action.setOperationType(ActionSignalHead.OperationType.Lit);
1166                break;
1167
1168            case SET_SIGNAL_DARK:
1169                action.setOperationType(ActionSignalHead.OperationType.NotLit);
1170                break;
1171
1172            default:
1173                throw new InvalidConditionalVariableException(
1174                        Bundle.getMessage("ActionBadSignalHeadType", ca.getType().toString()));
1175        }
1176
1177        return action;
1178    }
1179
1180
1181    private DigitalActionBean getSignalMastAction(@Nonnull ConditionalAction ca, SignalMast sm, String reference) throws JmriException {
1182        ActionSignalMast action =
1183                new ActionSignalMast(InstanceManager.getDefault(DigitalActionManager.class)
1184                        .getAutoSystemName(), null);
1185
1186        if (reference != null) {
1187            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1188            action.getSelectNamedBean().setReference(reference);
1189        } else {
1190            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1191            action.getSelectNamedBean().setNamedBean(sm);
1192        }
1193        action.setOperationAddressing(NamedBeanAddressing.Direct);
1194        action.setAspectAddressing(NamedBeanAddressing.Direct);
1195
1196        switch (ca.getType()) {
1197            case SET_SIGNALMAST_ASPECT:
1198                action.setOperationType(ActionSignalMast.OperationType.Aspect);
1199                String aspect = ca.getActionString();
1200                if ( !aspect.isEmpty() && aspect.charAt(0) == '@') {
1201                    String memName = aspect.substring(1);
1202                    action.setAspectAddressing(NamedBeanAddressing.Reference);
1203                    action.setAspectReference("{" + memName + "}");
1204                } else {
1205                    action.setAspect(aspect);
1206                }
1207                break;
1208
1209            case SET_SIGNALMAST_HELD:
1210                action.setOperationType(ActionSignalMast.OperationType.Held);
1211                break;
1212
1213            case CLEAR_SIGNALMAST_HELD:
1214                action.setOperationType(ActionSignalMast.OperationType.NotHeld);
1215                break;
1216
1217            case SET_SIGNALMAST_LIT:
1218                action.setOperationType(ActionSignalMast.OperationType.Lit);
1219                break;
1220
1221            case SET_SIGNALMAST_DARK:
1222                action.setOperationType(ActionSignalMast.OperationType.NotLit);
1223                break;
1224
1225            default:
1226                throw new InvalidConditionalVariableException(
1227                        Bundle.getMessage("ActionBadSignalMastType", ca.getType().toString()));
1228        }
1229
1230        return action;
1231    }
1232
1233
1234    private DigitalActionBean getEntryExitAction(@Nonnull ConditionalAction ca, DestinationPoints dp, String reference) throws JmriException {
1235        ActionEntryExit action =
1236                new ActionEntryExit(InstanceManager.getDefault(DigitalActionManager.class)
1237                        .getAutoSystemName(), null);
1238
1239        if (reference != null) {
1240            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1241            action.getSelectNamedBean().setReference(reference);
1242        } else {
1243            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1244            action.getSelectNamedBean().setNamedBean(dp);
1245        }
1246        action.getSelectEnum().setAddressing(NamedBeanAddressing.Direct);
1247
1248        switch (ca.getType()) {
1249            case SET_NXPAIR_ENABLED:
1250                action.getSelectEnum().setEnum(ActionEntryExit.Operation.SetNXPairEnabled);
1251                break;
1252            case SET_NXPAIR_DISABLED:
1253                action.getSelectEnum().setEnum(ActionEntryExit.Operation.SetNXPairDisabled);
1254                break;
1255            case SET_NXPAIR_SEGMENT:
1256                action.getSelectEnum().setEnum(ActionEntryExit.Operation.SetNXPairSegment);
1257                break;
1258            default:
1259                throw new InvalidConditionalVariableException(
1260                        Bundle.getMessage("ActionBadEntryExitType", ca.getType().toString()));
1261        }
1262
1263        return action;
1264    }
1265
1266
1267    private DigitalActionBean getWarrantAction(@Nonnull ConditionalAction ca, Warrant w, String reference) throws JmriException {
1268        ActionWarrant action =
1269                new ActionWarrant(InstanceManager.getDefault(DigitalActionManager.class)
1270                        .getAutoSystemName(), null);
1271
1272        if (reference != null) {
1273            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1274            action.getSelectNamedBean().setReference(reference);
1275        } else {
1276            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1277            action.getSelectNamedBean().setNamedBean(w);
1278        }
1279        action.getSelectEnum().setAddressing(NamedBeanAddressing.Direct);
1280
1281        switch (ca.getType()) {
1282            case ALLOCATE_WARRANT_ROUTE:
1283                action.getSelectEnum().setEnum(ActionWarrant.DirectOperation.AllocateWarrantRoute);
1284                break;
1285
1286            case DEALLOCATE_WARRANT_ROUTE:
1287                action.getSelectEnum().setEnum(ActionWarrant.DirectOperation.DeallocateWarrant);
1288                break;
1289
1290            case SET_ROUTE_TURNOUTS:
1291                action.getSelectEnum().setEnum(ActionWarrant.DirectOperation.SetRouteTurnouts);
1292                break;
1293
1294            case AUTO_RUN_WARRANT:
1295                action.getSelectEnum().setEnum(ActionWarrant.DirectOperation.AutoRunTrain);
1296                break;
1297
1298            case MANUAL_RUN_WARRANT:
1299                action.getSelectEnum().setEnum(ActionWarrant.DirectOperation.ManuallyRunTrain);
1300                break;
1301
1302            case CONTROL_TRAIN:
1303                action.getSelectEnum().setEnum(ActionWarrant.DirectOperation.ControlAutoTrain);
1304                action.setControlAutoTrain(ActionWarrant.ControlAutoTrain.values()[ca.getActionData() - 1]);
1305                break;
1306
1307            case SET_TRAIN_ID:
1308                action.getSelectEnum().setEnum(ActionWarrant.DirectOperation.SetTrainId);
1309                String idData = ca.getActionString();
1310                if (idData.isEmpty()) {
1311                    throw new InvalidConditionalActionException(
1312                            Bundle.getMessage("ActionBadWarrantValue", ca.getType().toString()));
1313                }
1314                if (idData.startsWith("@")) {
1315                    // indirect
1316                    String ref = "{" + idData.substring(1) + "}";
1317                    action.setDataAddressing(NamedBeanAddressing.Reference);
1318                    action.setDataReference(ref);
1319                } else {
1320                    action.setDataAddressing(NamedBeanAddressing.Direct);
1321                    action.setTrainData(idData);
1322                }
1323                break;
1324
1325            case SET_TRAIN_NAME:
1326                action.getSelectEnum().setEnum(ActionWarrant.DirectOperation.SetTrainName);
1327                String nameData = ca.getActionString();
1328                if (nameData.isEmpty()) {
1329                    throw new InvalidConditionalActionException(
1330                            Bundle.getMessage("ActionBadWarrantValue", ca.getType().toString()));
1331                }
1332                if (nameData.startsWith("@")) {
1333                    // indirect
1334                    String ref = "{" + nameData.substring(1) + "}";
1335                    action.setDataAddressing(NamedBeanAddressing.Reference);
1336                    action.setDataReference(ref);
1337                } else {
1338                    action.setDataAddressing(NamedBeanAddressing.Direct);
1339                    action.setTrainData(nameData);
1340                }
1341                break;
1342
1343            case GET_TRAIN_LOCATION:
1344                action.getSelectEnum().setEnum(ActionWarrant.DirectOperation.GetTrainLocation);
1345                String locData = ca.getActionString();
1346                if (locData.isEmpty()) {
1347                    throw new InvalidConditionalActionException(
1348                            Bundle.getMessage("ActionBadWarrantValue", ca.getType().toString()));
1349                }
1350                if (locData.startsWith("@")) {
1351                    // indirect
1352                    String ref = "{" + locData.substring(1) + "}";
1353                    action.setDataAddressing(NamedBeanAddressing.Reference);
1354                    action.setDataReference(ref);
1355                } else {
1356                    action.setDataAddressing(NamedBeanAddressing.Direct);
1357                    action.getSelectMemoryNamedBean().setNamedBean(locData);
1358//                    action.setTrainData(locData);
1359                }
1360                break;
1361
1362            default:
1363                throw new InvalidConditionalVariableException(
1364                        Bundle.getMessage("ActionBadWarrantType", ca.getType().toString()));
1365        }
1366
1367        return action;
1368    }
1369
1370
1371    private DigitalActionBean getOBlockAction(@Nonnull ConditionalAction ca, OBlock b, String reference) throws JmriException {
1372
1373        ActionOBlock action =
1374                new ActionOBlock(InstanceManager.getDefault(DigitalActionManager.class)
1375                        .getAutoSystemName(), null);
1376
1377        if (reference != null) {
1378            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1379            action.getSelectNamedBean().setReference(reference);
1380        } else {
1381            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1382            action.getSelectNamedBean().setNamedBean(b);
1383        }
1384        action.getSelectEnum().setAddressing(NamedBeanAddressing.Direct);
1385
1386        String oblockData;
1387
1388        switch (ca.getType()) {
1389            case DEALLOCATE_BLOCK:
1390                action.getSelectEnum().setEnum(ActionOBlock.DirectOperation.Deallocate);
1391                break;
1392
1393            case SET_BLOCK_VALUE:
1394                action.getSelectEnum().setEnum(ActionOBlock.DirectOperation.SetValue);
1395                oblockData = ca.getActionString();
1396                if (oblockData.isEmpty()) {
1397                    throw new InvalidConditionalActionException(
1398                            Bundle.getMessage("ActionBadOBlockValue", ca.getType().toString()));
1399                }
1400                if (oblockData.startsWith("@")) {
1401                    // indirect
1402                    String ref = "{" + oblockData.substring(1) + "}";
1403                    action.setDataAddressing(NamedBeanAddressing.Reference);
1404                    action.setDataReference(ref);
1405                } else {
1406                    action.setDataAddressing(NamedBeanAddressing.Direct);
1407                    action.setOBlockValue(oblockData);
1408                }
1409                break;
1410
1411            case SET_BLOCK_ERROR:
1412                action.getSelectEnum().setEnum(ActionOBlock.DirectOperation.SetError);
1413                break;
1414
1415            case CLEAR_BLOCK_ERROR:
1416                action.getSelectEnum().setEnum(ActionOBlock.DirectOperation.ClearError);
1417                break;
1418
1419            case SET_BLOCK_OUT_OF_SERVICE:
1420                action.getSelectEnum().setEnum(ActionOBlock.DirectOperation.SetOutOfService);
1421                break;
1422
1423            case SET_BLOCK_IN_SERVICE:
1424                action.getSelectEnum().setEnum(ActionOBlock.DirectOperation.ClearOutOfService);
1425                break;
1426
1427            case GET_BLOCK_WARRANT:
1428                action.getSelectEnum().setEnum(ActionOBlock.DirectOperation.GetBlockWarrant);
1429                oblockData = ca.getActionString();
1430                if (oblockData.isEmpty()) {
1431                    throw new InvalidConditionalActionException(
1432                            Bundle.getMessage("ActionBadOBlockMemory", ca.getType().toString()));
1433                }
1434                action.getSelectMemoryNamedBean().setNamedBean(oblockData);
1435                break;
1436
1437            case GET_BLOCK_TRAIN_NAME:
1438                action.getSelectEnum().setEnum(ActionOBlock.DirectOperation.GetBlockValue);
1439                oblockData = ca.getActionString();
1440                if (oblockData.isEmpty()) {
1441                    throw new InvalidConditionalActionException(
1442                            Bundle.getMessage("ActionBadOBlockMemory", ca.getType().toString()));
1443                }
1444                action.getSelectMemoryNamedBean().setNamedBean(oblockData);
1445                break;
1446
1447            default:
1448                throw new InvalidConditionalVariableException(
1449                        Bundle.getMessage("ActionBadOBlockType", ca.getType().toString()));
1450        }
1451
1452        return action;
1453    }
1454
1455
1456    private DigitalActionBean getEnableLogixAction(@Nonnull ConditionalAction ca) throws JmriException {
1457        EnableLogix action =
1458                new EnableLogix(InstanceManager.getDefault(DigitalActionManager.class)
1459                        .getAutoSystemName(), null);
1460
1461        action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1462        action.getSelectEnum().setAddressing(NamedBeanAddressing.Direct);
1463
1464        String devName = ca.getDeviceName();
1465        if (devName != null) {
1466            if (devName.length() > 0 && devName.charAt(0) == '@') {
1467                String memName = devName.substring(1);
1468                action.getSelectEnum().setAddressing(NamedBeanAddressing.Reference);
1469                action.getSelectEnum().setReference("{" + memName + "}");
1470            } else {
1471                action.getSelectNamedBean().setNamedBean(devName);
1472            }
1473        }
1474
1475        switch (ca.getType()) {
1476            case ENABLE_LOGIX:
1477                action.getSelectEnum().setEnum(EnableLogix.Operation.Enable);
1478                break;
1479
1480            case DISABLE_LOGIX:
1481                action.getSelectEnum().setEnum(EnableLogix.Operation.Disable);
1482                break;
1483
1484            default:
1485                throw new InvalidConditionalVariableException(
1486                        Bundle.getMessage("ActionBadEnableLogixType", ca.getType().toString()));
1487        }
1488
1489        return action;
1490    }
1491
1492
1493    private DigitalActionBean getClockAction(@Nonnull ConditionalAction ca) throws JmriException {
1494        ActionClock action =
1495                new ActionClock(InstanceManager.getDefault(DigitalActionManager.class)
1496                        .getAutoSystemName(), null);
1497
1498        switch (ca.getType()) {
1499            case START_FAST_CLOCK:
1500                action.getSelectEnum().setEnum(ActionClock.ClockState.StartClock);
1501                break;
1502
1503            case STOP_FAST_CLOCK:
1504                action.getSelectEnum().setEnum(ActionClock.ClockState.StopClock);
1505                break;
1506
1507            case SET_FAST_CLOCK_TIME:
1508                action.getSelectEnum().setEnum(ActionClock.ClockState.SetClock);
1509                action.getSelectTime().setValue(ca.getActionData());
1510                break;
1511
1512            default:
1513                throw new InvalidConditionalVariableException(
1514                        Bundle.getMessage("ActionBadSensorType", ca.getType().toString()));
1515        }
1516
1517        return action;
1518    }
1519
1520
1521    private DigitalActionBean getAudioAction(@Nonnull ConditionalAction ca) throws JmriException {
1522        ActionAudio action =
1523                new ActionAudio(InstanceManager.getDefault(DigitalActionManager.class)
1524                        .getAutoSystemName(), null);
1525
1526        action.getSelectEnum().setAddressing(NamedBeanAddressing.Direct);
1527        action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1528
1529        String sound = ca.getActionString();
1530        if ( !sound.isEmpty() && sound.charAt(0) == '@') {
1531            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1532            action.getSelectNamedBean().setReference(sound.substring(1));
1533        } else {
1534            Audio audio = InstanceManager.getDefault(jmri.AudioManager.class).getAudio(ca.getDeviceName());
1535            if ( audio != null ) {
1536                action.getSelectNamedBean().setNamedBean(audio);
1537            }
1538        }
1539
1540        switch (ca.getActionData()) {
1541            case Audio.CMD_PLAY:
1542                action.getSelectEnum().setEnum(ActionAudio.Operation.Play);
1543                break;
1544            case Audio.CMD_STOP:
1545                action.getSelectEnum().setEnum(ActionAudio.Operation.Stop);
1546                break;
1547            case Audio.CMD_PLAY_TOGGLE:
1548                action.getSelectEnum().setEnum(ActionAudio.Operation.PlayToggle);
1549                break;
1550            case Audio.CMD_PAUSE:
1551                action.getSelectEnum().setEnum(ActionAudio.Operation.Pause);
1552                break;
1553            case Audio.CMD_RESUME:
1554                action.getSelectEnum().setEnum(ActionAudio.Operation.Resume);
1555                break;
1556            case Audio.CMD_PAUSE_TOGGLE:
1557                action.getSelectEnum().setEnum(ActionAudio.Operation.PauseToggle);
1558                break;
1559            case Audio.CMD_REWIND:
1560                action.getSelectEnum().setEnum(ActionAudio.Operation.Rewind);
1561                break;
1562            case Audio.CMD_FADE_IN:
1563                action.getSelectEnum().setEnum(ActionAudio.Operation.FadeIn);
1564                break;
1565            case Audio.CMD_FADE_OUT:
1566                action.getSelectEnum().setEnum(ActionAudio.Operation.FadeOut);
1567                break;
1568            case Audio.CMD_RESET_POSITION:
1569                action.getSelectEnum().setEnum(ActionAudio.Operation.ResetPosition);
1570                break;
1571            default:
1572                break;
1573        }
1574
1575        return action;
1576    }
1577
1578    private DigitalActionBean getSoundAction(@Nonnull ConditionalAction ca) throws JmriException {
1579        ActionSound action =
1580                new ActionSound(InstanceManager.getDefault(DigitalActionManager.class)
1581                        .getAutoSystemName(), null);
1582
1583        action.getSelectEnum().setAddressing(NamedBeanAddressing.Direct);
1584        action.setSoundAddressing(NamedBeanAddressing.Direct);
1585
1586        String sound = ca.getActionString();
1587        if ( !sound.isEmpty() && sound.charAt(0) == '@') {
1588            action.setSoundAddressing(NamedBeanAddressing.Reference);
1589            action.setSoundReference(sound.substring(1));
1590        } else {
1591            action.setSound(sound);
1592        }
1593
1594        return action;
1595    }
1596
1597    private DigitalActionBean getAudioOrSoundAction(@Nonnull ConditionalAction ca) throws JmriException {
1598        switch (ca.getType()) {
1599            case CONTROL_AUDIO:
1600                return getAudioAction(ca);
1601
1602            case PLAY_SOUND:
1603                return getSoundAction(ca);
1604
1605            default:
1606                throw new InvalidConditionalVariableException(
1607                        Bundle.getMessage("ConditionalBadAudioOrSoundType", ca.getType().toString()));
1608        }
1609    }
1610
1611
1612    private DigitalActionBean getScriptAction(@Nonnull ConditionalAction ca) throws JmriException {
1613        ActionScript action =
1614                new ActionScript(InstanceManager.getDefault(DigitalActionManager.class)
1615                        .getAutoSystemName(), null);
1616
1617        action.setOperationAddressing(NamedBeanAddressing.Direct);
1618        action.setScriptAddressing(NamedBeanAddressing.Direct);
1619
1620        String script = ca.getActionString();
1621        if ( !script.isEmpty() && script.charAt(0) == '@') {
1622            action.setScriptAddressing(NamedBeanAddressing.Reference);
1623            action.setScriptReference(script.substring(1));
1624        } else {
1625            action.setScript(script);
1626        }
1627
1628        switch (ca.getType()) {
1629            case RUN_SCRIPT:
1630                action.setOperationType(ActionScript.OperationType.RunScript);
1631                break;
1632
1633            case JYTHON_COMMAND:
1634                action.setOperationType(ActionScript.OperationType.SingleLineCommand);
1635                break;
1636
1637            default:
1638                throw new InvalidConditionalVariableException(
1639                        Bundle.getMessage("ActionBadScriptType", ca.getType().toString()));
1640        }
1641
1642        return action;
1643    }
1644
1645
1646    private DigitalActionBean getRouteAction(@Nonnull ConditionalAction ca, Route b, String reference) throws JmriException {
1647        TriggerRoute action =
1648                new TriggerRoute(InstanceManager.getDefault(DigitalActionManager.class)
1649                        .getAutoSystemName(), null);
1650
1651        action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1652        action.getSelectEnum().setAddressing(NamedBeanAddressing.Direct);
1653
1654        String devName = ca.getDeviceName();
1655        if (devName != null) {
1656            if (devName.length() > 0 && devName.charAt(0) == '@') {
1657                String memName = devName.substring(1);
1658                action.getSelectEnum().setAddressing(NamedBeanAddressing.Reference);
1659                action.getSelectEnum().setReference("{" + memName + "}");
1660            } else {
1661                action.getSelectNamedBean().setNamedBean(devName);
1662            }
1663        }
1664
1665        switch (ca.getType()) {
1666            case TRIGGER_ROUTE:
1667                action.getSelectEnum().setEnum(TriggerRoute.Operation.TriggerRoute);
1668                break;
1669
1670            default:
1671                throw new InvalidConditionalVariableException(
1672                        Bundle.getMessage("ActionBadRouteType", ca.getType().toString()));
1673        }
1674
1675        return action;
1676    }
1677
1678
1679    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ImportConditional.class);
1680
1681}