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) throw new RuntimeException("Cannot create new ConditionalNG with name: \"" + userName + "\"");
065
066            _conditionalNG = conditionalNG;
067        } else {
068            _conditionalNG = null;
069        }
070    }
071
072    public ConditionalNG getConditionalNG() {
073        return _conditionalNG;
074    }
075
076    public void doImport() throws SocketAlreadyConnectedException, JmriException {
077
078        Logix logix = new Logix(InstanceManager.getDefault(DigitalActionManager.class).getAutoSystemName(), null);
079
080        logix.setExecuteType(_conditional.getTriggerOnChange()
081                ? Logix.ExecuteType.ExecuteOnChange
082                : Logix.ExecuteType.ExecuteAlways);
083
084        Conditional.AntecedentOperator ao = _conditional.getLogicType();
085        String antecedentExpression = _conditional.getAntecedentExpression();
086        List<ConditionalVariable> conditionalVariables = _conditional.getCopyOfStateVariables();
087        List<ConditionalAction> conditionalActions = _conditional.getCopyOfActions();
088
089        DigitalExpressionBean expression;
090        switch (ao) {
091            case ALL_AND:
092                expression = new And(InstanceManager.getDefault(DigitalExpressionManager.class).getAutoSystemName(), null);
093                break;
094            case ALL_OR:
095                expression = new Or(InstanceManager.getDefault(DigitalExpressionManager.class).getAutoSystemName(), null);
096                break;
097            case MIXED:
098                expression = new Antecedent(InstanceManager.getDefault(DigitalExpressionManager.class).getAutoSystemName(), null);
099                ((Antecedent)expression).setAntecedent(antecedentExpression);
100                break;
101            default:
102                return;
103        }
104
105        // Is the Conditional a RTXINITIALIZER?
106        if ((conditionalVariables.size() == 1) && (conditionalVariables.get(0).getType().getItemType() == Conditional.ItemType.NONE)) {
107            expression =
108                    new TriggerOnce(InstanceManager.getDefault(DigitalExpressionManager.class)
109                            .getAutoSystemName(), null);
110
111            True trueExpression =
112                    new True(InstanceManager.getDefault(DigitalExpressionManager.class)
113                            .getAutoSystemName(), null);
114            if (!_dryRun) {
115                MaleSocket socket = InstanceManager.getDefault(DigitalExpressionManager.class)
116                        .registerExpression(trueExpression);
117                expression.getChild(0).connect(socket);
118            }
119        } else {
120            buildExpression(expression, conditionalVariables, ao != Conditional.AntecedentOperator.MIXED);
121        }
122
123        DigitalBooleanMany many =
124                new DigitalBooleanMany(InstanceManager.getDefault(
125                        DigitalBooleanActionManager.class).getAutoSystemName(), null);
126
127        buildAction(many, conditionalActions);
128
129        if (!_dryRun) {
130            MaleSocket expressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class).registerExpression(expression);
131            logix.getExpressionSocket().connect(expressionSocket);
132
133            MaleSocket manySocket = InstanceManager.getDefault(DigitalBooleanActionManager.class).registerAction(many);
134            logix.getActionSocket().connect(manySocket);
135
136            MaleSocket logixAction = InstanceManager.getDefault(DigitalActionManager.class).registerAction(logix);
137            _conditionalNG.getChild(0).connect(logixAction);
138        }
139    }
140
141
142    private void buildExpression(
143            DigitalExpressionBean expression,
144            List<ConditionalVariable> conditionalVariables,
145            boolean allowNot)
146            throws SocketAlreadyConnectedException, JmriException {
147
148        for (int i=0; i < conditionalVariables.size(); i++) {
149            jmri.ConditionalVariable cv = conditionalVariables.get(i);
150            NamedBean nb = cv.getBean();
151            AtomicBoolean isNegated = new AtomicBoolean(cv.isNegated() && allowNot);
152            DigitalExpressionBean newExpression;
153            switch (cv.getType().getItemType()) {
154                case SENSOR:
155                    Sensor sn = (Sensor)nb;
156                    newExpression = getSensorExpression(cv, sn, isNegated);
157                    break;
158                case TURNOUT:
159                    Turnout tn = (Turnout)nb;
160                    newExpression = getTurnoutExpression(cv, tn, isNegated);
161                    break;
162                case MEMORY:
163                    Memory my = (Memory)nb;
164                    newExpression = getMemoryExpression(cv, my);
165                    break;
166                case LIGHT:
167                    Light l = (Light)nb;
168                    newExpression = getLightExpression(cv, l, isNegated);
169                    break;
170                case SIGNALHEAD:
171                    SignalHead s = (SignalHead)nb;
172                    newExpression = getSignalHeadExpression(cv, s, isNegated);
173                    break;
174                case SIGNALMAST:
175                    SignalMast sm = (SignalMast)nb;
176                    newExpression = getSignalMastExpression(cv, sm, isNegated);
177                    break;
178                case ENTRYEXIT:
179                    DestinationPoints dp = (DestinationPoints)nb;
180                    newExpression = getEntryExitExpression(cv, dp, isNegated);
181                    break;
182                case CONDITIONAL:
183                    Conditional c = (Conditional)nb;
184                    newExpression = getConditionalExpression(cv, c, isNegated);
185                    break;
186                case CLOCK:
187                    newExpression = getFastClockExpression(cv, isNegated);
188                    break;
189                case WARRANT:
190                    Warrant w = (Warrant)nb;
191                    newExpression = getWarrantExpression(cv, w, isNegated);
192                    break;
193                case OBLOCK:
194                    OBlock b = (OBlock)nb;
195                    newExpression = getOBlockExpression(cv, b, isNegated);
196                    break;
197                default:
198                    newExpression = null;
199                    log.error("Unexpected type in ImportConditional.doImport(): {} -> {}", cv.getType().name(), cv.getType().getItemType().name());
200                    break;
201            }
202
203            if (newExpression != null) {
204
205                boolean doTriggerActions = cv.doTriggerActions();
206
207                if (isNegated.get()) {  // Some expressions have already handled Not
208                    Not notExpression = new Not(InstanceManager.getDefault(DigitalExpressionManager.class)
209                            .getAutoSystemName(), null);
210
211                    if (!_dryRun) {
212                        MaleSocket newExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class).registerExpression(newExpression);
213                        newExpressionSocket.setListen(doTriggerActions);
214                        doTriggerActions = true;    // We don't want the Not expression to disable listen.
215                        notExpression.getChild(0).connect(newExpressionSocket);
216                    }
217                    newExpression = notExpression;
218                }
219
220                if (!_dryRun) {
221                    MaleSocket newExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class).registerExpression(newExpression);
222                    newExpressionSocket.setListen(doTriggerActions);
223                    expression.getChild(i).connect(newExpressionSocket);
224                }
225            } else {
226                log.error("ImportConditional.doImport() did not created an expression for type: {} -> {}", cv.getType().name(), cv.getType().getItemType().name());
227            }
228        }
229    }
230
231
232    private void buildAction(DigitalBooleanMany many, List<ConditionalAction> conditionalActions)
233            throws SocketAlreadyConnectedException, JmriException {
234
235        for (int i=0; i < conditionalActions.size(); i++) {
236            ConditionalAction ca = conditionalActions.get(i);
237
238            DigitalBooleanLogixAction.When trigger;
239            switch (ca.getOption()) {
240                case Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE:
241                    trigger = DigitalBooleanLogixAction.When.True;
242                    break;
243
244                case Conditional.ACTION_OPTION_ON_CHANGE_TO_FALSE:
245                    trigger = DigitalBooleanLogixAction.When.False;
246                    break;
247
248                case Conditional.ACTION_OPTION_ON_CHANGE:
249                    trigger = DigitalBooleanLogixAction.When.Either;
250                    break;
251
252                default:
253                    throw new InvalidConditionalActionException(
254                            Bundle.getMessage("ActionBadTrigger", ca.getOption()));
255            }
256
257            DigitalBooleanActionBean booleanAction =
258                    new DigitalBooleanLogixAction(InstanceManager.getDefault(DigitalBooleanActionManager.class).getAutoSystemName(), null, trigger);
259
260            buildAction(booleanAction, ca);
261
262            if (!_dryRun) {
263                MaleSocket newBooleanActionSocket = InstanceManager.getDefault(DigitalBooleanActionManager.class).registerAction(booleanAction);
264                many.getChild(i).connect(newBooleanActionSocket);
265            }
266        }
267    }
268
269    private void buildAction(DigitalBooleanActionBean action, ConditionalAction conditionalAction)
270            throws SocketAlreadyConnectedException, JmriException {
271
272
273        String reference = null;
274        String devName = conditionalAction.getDeviceName();
275        if (devName != null && devName.length() > 0 && devName.charAt(0) == '@') {
276            reference = "{"+devName.substring(1)+"}";
277        }
278
279        NamedBean nb = conditionalAction.getBean();
280//        System.err.format("nb: %s%n", nb == null ? null : nb.getSystemName());
281        DigitalActionBean newAction;
282        switch (conditionalAction.getType().getItemType()) {
283            case SENSOR:
284                Sensor sn = (Sensor)nb;
285                newAction = getSensorAction(conditionalAction, sn, reference);
286                break;
287            case TURNOUT:
288                Turnout tn = (Turnout)nb;
289                newAction = getTurnoutAction(conditionalAction, tn, reference);
290                break;
291            case MEMORY:
292                Memory my = (Memory)nb;
293                newAction = getMemoryAction(conditionalAction, my, reference);
294                break;
295            case LIGHT:
296                Light l = (Light)nb;
297                newAction = getLightAction(conditionalAction, l, reference);
298                break;
299            case SIGNALHEAD:
300                SignalHead s = (SignalHead)nb;
301                newAction = getSignalHeadAction(conditionalAction, s, reference);
302                break;
303            case SIGNALMAST:
304                SignalMast sm = (SignalMast)nb;
305                newAction = getSignalMastAction(conditionalAction, sm, reference);
306                break;
307            case ENTRYEXIT:
308                DestinationPoints dp = (DestinationPoints)nb;
309                newAction = getEntryExitAction(conditionalAction, dp, reference);
310                break;
311            case WARRANT:
312                Warrant w = (Warrant)nb;
313                newAction = getWarrantAction(conditionalAction, w, reference);
314                break;
315            case OBLOCK:
316                OBlock b = (OBlock)nb;
317                newAction = getOBlockAction(conditionalAction, b, reference);
318                break;
319
320            case LOGIX:
321                newAction = getEnableLogixAction(conditionalAction);
322                break;
323
324            case CLOCK:
325                newAction = getClockAction(conditionalAction);
326                break;
327
328            case AUDIO:
329                newAction = getAudioOrSoundAction(conditionalAction);
330                break;
331
332            case SCRIPT:
333                newAction = getScriptAction(conditionalAction);
334                break;
335
336            case OTHER:
337                Route r = (Route) nb;
338                newAction = getRouteAction(conditionalAction, r, reference);
339                break;
340
341            default:
342                newAction = null;
343                log.warn("Unexpected type in ImportConditional.doImport(): {} -> {}", conditionalAction.getType(), conditionalAction.getType().getItemType());
344                break;
345        }
346
347        if (newAction != null) {
348            if (!_dryRun) {
349                MaleSocket newActionSocket = InstanceManager.getDefault(DigitalActionManager.class).registerAction(newAction);
350                action.getChild(0).connect(newActionSocket);
351            }
352        } else {
353            log.error("ImportConditional.doImport() did not created an action for type: {} -> {}", conditionalAction.getType(), conditionalAction.getType().getItemType());
354        }
355    }
356
357
358    private DigitalExpressionBean getSensorExpression(
359            @Nonnull ConditionalVariable cv,
360            Sensor sn,
361            AtomicBoolean isNegated)
362            throws JmriException {
363
364        ExpressionSensor expression =
365                new ExpressionSensor(InstanceManager.getDefault(DigitalExpressionManager.class)
366                        .getAutoSystemName(), null);
367
368//        System.err.format("Sensor: %s%n", sn == null ? null : sn.getSystemName());
369
370        expression.getSelectNamedBean().setNamedBean(sn);
371
372        if (isNegated.get()) {
373            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
374            isNegated.set(false);
375        }
376
377        switch (cv.getType()) {
378            case SENSOR_ACTIVE:
379                expression.getSelectEnum().setEnum(ExpressionSensor.SensorState.Active);
380                break;
381            case SENSOR_INACTIVE:
382                expression.getSelectEnum().setEnum(ExpressionSensor.SensorState.Inactive);
383                break;
384            default:
385                throw new InvalidConditionalVariableException(
386                        Bundle.getMessage("ConditionalBadSensorType", cv.getType().toString()));
387        }
388
389        return expression;
390    }
391
392
393    private DigitalExpressionBean getTurnoutExpression(
394            @Nonnull ConditionalVariable cv,
395            Turnout tn,
396            AtomicBoolean isNegated)
397            throws JmriException {
398
399        ExpressionTurnout expression =
400                new ExpressionTurnout(InstanceManager.getDefault(DigitalExpressionManager.class)
401                        .getAutoSystemName(), null);
402
403        expression.getSelectNamedBean().setNamedBean(tn);
404
405        if (isNegated.get()) {
406            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
407            isNegated.set(false);
408        }
409
410        switch (cv.getType()) {
411            case TURNOUT_CLOSED:
412                expression.setBeanState(ExpressionTurnout.TurnoutState.Closed);
413                break;
414            case TURNOUT_THROWN:
415                expression.setBeanState(ExpressionTurnout.TurnoutState.Thrown);
416                break;
417            default:
418                throw new InvalidConditionalVariableException(
419                        Bundle.getMessage("ConditionalBadTurnoutType", cv.getType().toString()));
420        }
421
422        return expression;
423    }
424
425
426    private DigitalExpressionBean getMemoryExpression(
427            @Nonnull ConditionalVariable cv, Memory my)
428            throws JmriException {
429
430        ExpressionMemory expression =
431                new ExpressionMemory(InstanceManager.getDefault(DigitalExpressionManager.class)
432                        .getAutoSystemName(), null);
433
434        expression.getSelectNamedBean().setNamedBean(my);
435
436        switch (cv.getNum1()) {
437            case ConditionalVariable.EQUAL:
438                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.Equal);
439                break;
440            case ConditionalVariable.LESS_THAN:
441                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.LessThan);
442                break;
443            case ConditionalVariable.LESS_THAN_OR_EQUAL:
444                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.LessThanOrEqual);
445                break;
446            case ConditionalVariable.GREATER_THAN:
447                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.GreaterThan);
448                break;
449            case ConditionalVariable.GREATER_THAN_OR_EQUAL:
450                expression.setMemoryOperation(ExpressionMemory.MemoryOperation.GreaterThanOrEqual);
451                break;
452            default:
453                throw new InvalidConditionalVariableException(
454                        Bundle.getMessage("ConditionalBadMemoryNum1", cv.getType().toString()));
455        }
456
457        Memory memory;
458        switch (cv.getType()) {
459            case MEMORY_EQUALS:
460                expression.setCompareTo(ExpressionMemory.CompareTo.Value);
461                expression.setCaseInsensitive(false);
462                expression.setConstantValue(cv.getDataString());
463                break;
464            case MEMORY_EQUALS_INSENSITIVE:
465                expression.setCompareTo(ExpressionMemory.CompareTo.Value);
466                expression.setCaseInsensitive(true);
467                expression.setConstantValue(cv.getDataString());
468                break;
469            case MEMORY_COMPARE:
470                expression.setCompareTo(ExpressionMemory.CompareTo.Memory);
471                expression.setCaseInsensitive(false);
472                expression.getSelectOtherMemoryNamedBean().setNamedBean(cv.getDataString());
473                memory = InstanceManager.getDefault(MemoryManager.class).getMemory(cv.getDataString());
474                if (memory == null) {   // Logix allows the memory name in cv.getDataString() to be a system name without system prefix
475                    memory = InstanceManager.getDefault(MemoryManager.class).provide(cv.getDataString());
476                    expression.getSelectOtherMemoryNamedBean().setNamedBean(memory.getSystemName());
477                }
478                break;
479            case MEMORY_COMPARE_INSENSITIVE:
480                expression.setCompareTo(ExpressionMemory.CompareTo.Memory);
481                expression.setCaseInsensitive(true);
482                expression.getSelectOtherMemoryNamedBean().setNamedBean(cv.getDataString());
483                memory = InstanceManager.getDefault(MemoryManager.class).getMemory(cv.getDataString());
484                if (memory == null) {   // Logix allows the memory name in cv.getDataString() to be a system name without system prefix
485                    memory = InstanceManager.getDefault(MemoryManager.class).provide(cv.getDataString());
486                    expression.getSelectOtherMemoryNamedBean().setNamedBean(memory.getSystemName());
487                }
488                break;
489            default:
490                throw new InvalidConditionalVariableException(
491                        Bundle.getMessage("ConditionalBadMemoryType", cv.getType().toString()));
492        }
493
494        expression.setListenToOtherMemory(false);
495
496        return expression;
497    }
498
499
500    private DigitalExpressionBean getLightExpression(
501            @Nonnull ConditionalVariable cv,
502            Light ln,
503            AtomicBoolean isNegated)
504            throws JmriException {
505
506        ExpressionLight expression =
507                new ExpressionLight(InstanceManager.getDefault(DigitalExpressionManager.class)
508                        .getAutoSystemName(), null);
509
510        expression.getSelectNamedBean().setNamedBean(ln);
511
512        if (isNegated.get()) {
513            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
514            isNegated.set(false);
515        }
516
517        switch (cv.getType()) {
518            case LIGHT_ON:
519                expression.setBeanState(ExpressionLight.LightState.On);
520                break;
521            case LIGHT_OFF:
522                expression.setBeanState(ExpressionLight.LightState.Off);
523                break;
524            default:
525                throw new InvalidConditionalVariableException(
526                        Bundle.getMessage("ConditionalBadLightType", cv.getType().toString()));
527        }
528
529        return expression;
530    }
531
532
533    private DigitalExpressionBean getSignalHeadExpression(
534            @Nonnull ConditionalVariable cv,
535            SignalHead s,
536            AtomicBoolean isNegated)
537            throws JmriException {
538
539        ExpressionSignalHead expression =
540                new ExpressionSignalHead(InstanceManager.getDefault(DigitalExpressionManager.class)
541                        .getAutoSystemName(), null);
542
543        expression.getSelectNamedBean().setNamedBean(s);
544
545        ExpressionSignalHead.QueryType appearence =
546                isNegated.get() ? ExpressionSignalHead.QueryType.NotAppearance
547                : ExpressionSignalHead.QueryType.Appearance;
548
549        switch (cv.getType()) {
550            case SIGNAL_HEAD_RED:
551                expression.setQueryType(appearence);
552                expression.setAppearance(SignalHead.RED);
553                break;
554            case SIGNAL_HEAD_YELLOW:
555                expression.setQueryType(appearence);
556                expression.setAppearance(SignalHead.YELLOW);
557                break;
558            case SIGNAL_HEAD_GREEN:
559                expression.setQueryType(appearence);
560                expression.setAppearance(SignalHead.GREEN);
561                break;
562            case SIGNAL_HEAD_DARK:
563                expression.setQueryType(appearence);
564                expression.setAppearance(SignalHead.DARK);
565                break;
566            case SIGNAL_HEAD_FLASHRED:
567                expression.setQueryType(appearence);
568                expression.setAppearance(SignalHead.FLASHRED);
569                break;
570            case SIGNAL_HEAD_FLASHYELLOW:
571                expression.setQueryType(appearence);
572                expression.setAppearance(SignalHead.FLASHYELLOW);
573                break;
574            case SIGNAL_HEAD_FLASHGREEN:
575                expression.setQueryType(appearence);
576                expression.setAppearance(SignalHead.FLASHGREEN);
577                break;
578            case SIGNAL_HEAD_LUNAR:
579                expression.setQueryType(appearence);
580                expression.setAppearance(SignalHead.LUNAR);
581                break;
582            case SIGNAL_HEAD_FLASHLUNAR:
583                expression.setQueryType(appearence);
584                expression.setAppearance(SignalHead.FLASHLUNAR);
585                break;
586            case SIGNAL_HEAD_LIT:
587                expression.setQueryType(isNegated.get() ? ExpressionSignalHead.QueryType.NotLit : ExpressionSignalHead.QueryType.Lit);
588                break;
589            case SIGNAL_HEAD_HELD:
590                expression.setQueryType(isNegated.get() ? ExpressionSignalHead.QueryType.NotHeld : ExpressionSignalHead.QueryType.Held);
591                break;
592            default:
593                throw new InvalidConditionalVariableException(
594                        Bundle.getMessage("ConditionalBadSignalHeadType", cv.getType().toString()));
595        }
596
597        isNegated.set(false);   // We have already handled this
598
599        return expression;
600    }
601
602
603    private DigitalExpressionBean getSignalMastExpression(
604            @Nonnull ConditionalVariable cv,
605            SignalMast sm,
606            AtomicBoolean isNegated)
607            throws JmriException {
608
609        ExpressionSignalMast expression =
610                new ExpressionSignalMast(InstanceManager.getDefault(DigitalExpressionManager.class)
611                        .getAutoSystemName(), null);
612
613        expression.getSelectNamedBean().setNamedBean(sm);
614
615        ExpressionSignalMast.QueryType aspect =
616                isNegated.get() ? ExpressionSignalMast.QueryType.NotAspect
617                : ExpressionSignalMast.QueryType.Aspect;
618
619        switch (cv.getType()) {
620            case SIGNAL_MAST_ASPECT_EQUALS:
621                expression.setQueryType(aspect);
622                expression.setAspect(cv.getDataString());
623                break;
624            case SIGNAL_MAST_LIT:
625                expression.setQueryType(isNegated.get() ? ExpressionSignalMast.QueryType.NotLit : ExpressionSignalMast.QueryType.Lit);
626                break;
627            case SIGNAL_MAST_HELD:
628                expression.setQueryType(isNegated.get() ? ExpressionSignalMast.QueryType.NotHeld : ExpressionSignalMast.QueryType.Held);
629                break;
630            default:
631                throw new InvalidConditionalVariableException(
632                        Bundle.getMessage("ConditionalBadSignalMastType", cv.getType().toString()));
633        }
634
635        isNegated.set(false);   // We have already handled this
636
637        return expression;
638    }
639
640
641    private DigitalExpressionBean getEntryExitExpression(
642            @Nonnull ConditionalVariable cv,
643            DestinationPoints dp,
644            AtomicBoolean isNegated)
645            throws JmriException {
646
647        ExpressionEntryExit expression =
648                new ExpressionEntryExit(InstanceManager.getDefault(DigitalExpressionManager.class)
649                        .getAutoSystemName(), null);
650
651        expression.getSelectNamedBean().setNamedBean(dp);
652
653        if (isNegated.get()) {
654            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
655            isNegated.set(false);
656        }
657
658        switch (cv.getType()) {
659            case ENTRYEXIT_ACTIVE:
660                expression.setBeanState(ExpressionEntryExit.EntryExitState.Active);
661                break;
662            case ENTRYEXIT_INACTIVE:
663                expression.setBeanState(ExpressionEntryExit.EntryExitState.Inactive);
664                break;
665            default:
666                throw new InvalidConditionalVariableException(
667                        Bundle.getMessage("ConditionalBadEntryExitType", cv.getType().toString()));
668        }
669
670        return expression;
671    }
672
673
674    private DigitalExpressionBean getConditionalExpression(
675            @Nonnull ConditionalVariable cv,
676            Conditional cn,
677            AtomicBoolean isNegated)
678            throws JmriException {
679
680        ExpressionConditional expression =
681                new ExpressionConditional(InstanceManager.getDefault(DigitalExpressionManager.class)
682                        .getAutoSystemName(), null);
683
684        expression.getSelectNamedBean().setNamedBean(cn);
685
686        if (isNegated.get()) {
687            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
688            isNegated.set(false);
689        }
690
691        switch (cv.getType()) {
692            case CONDITIONAL_TRUE:
693                expression.setConditionalState(ExpressionConditional.ConditionalState.True);
694                break;
695            case CONDITIONAL_FALSE:
696                expression.setConditionalState(ExpressionConditional.ConditionalState.False);
697                break;
698            default:
699                throw new InvalidConditionalVariableException(
700                        Bundle.getMessage("ConditionalBadConditionalType", cv.getType().toString()));
701        }
702
703        return expression;
704    }
705
706
707    private DigitalExpressionBean getFastClockExpression(
708            @Nonnull ConditionalVariable cv,
709            AtomicBoolean isNegated)
710            throws JmriException {
711
712        ExpressionClock expression =
713                new ExpressionClock(InstanceManager.getDefault(DigitalExpressionManager.class)
714                        .getAutoSystemName(), null);
715
716        if (isNegated.get()) {
717            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
718            isNegated.set(false);
719        }
720
721        if (cv.getType() != Conditional.Type.FAST_CLOCK_RANGE) {
722            throw new InvalidConditionalVariableException(
723                    Bundle.getMessage("ConditionalBadFastClockType", cv.getType().toString()));
724        }
725                log.info("Found a clock range");
726
727        expression.setType(ExpressionClock.Type.FastClock);
728        expression.setRange(ConditionalVariable.fixMidnight(cv.getNum1()), ConditionalVariable.fixMidnight(cv.getNum2()));
729
730        return expression;
731    }
732
733
734    private DigitalExpressionBean getWarrantExpression(
735            @Nonnull ConditionalVariable cv,
736            Warrant w,
737            AtomicBoolean isNegated)
738            throws JmriException {
739
740        ExpressionWarrant expression =
741                new ExpressionWarrant(InstanceManager.getDefault(DigitalExpressionManager.class)
742                        .getAutoSystemName(), null);
743
744        expression.getSelectNamedBean().setNamedBean(w);
745
746        if (isNegated.get()) {
747            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
748            isNegated.set(false);
749        }
750
751        switch (cv.getType()) {
752            case ROUTE_FREE:
753                expression.setBeanState(ExpressionWarrant.WarrantState.RouteFree);
754                break;
755            case ROUTE_OCCUPIED:
756                expression.setBeanState(ExpressionWarrant.WarrantState.RouteOccupied);
757                break;
758            case ROUTE_ALLOCATED:
759                expression.setBeanState(ExpressionWarrant.WarrantState.RouteAllocated);
760                break;
761            case ROUTE_SET:
762                expression.setBeanState(ExpressionWarrant.WarrantState.RouteSet);
763                break;
764            case TRAIN_RUNNING:
765                expression.setBeanState(ExpressionWarrant.WarrantState.TrainRunning);
766                break;
767            default:
768                throw new InvalidConditionalVariableException(
769                        Bundle.getMessage("ConditionalBadWarrantType", cv.getType().toString()));
770        }
771
772        return expression;
773    }
774
775
776    private DigitalExpressionBean getOBlockExpression(
777            @Nonnull ConditionalVariable cv,
778            OBlock b,
779            AtomicBoolean isNegated)
780            throws JmriException {
781
782        ExpressionOBlock expression =
783                new ExpressionOBlock(InstanceManager.getDefault(DigitalExpressionManager.class)
784                        .getAutoSystemName(), null);
785
786        if (isNegated.get()) {
787            expression.set_Is_IsNot(Is_IsNot_Enum.IsNot);
788            isNegated.set(false);
789        }
790
791        OBlock.OBlockStatus oblockStatus = OBlock.OBlockStatus.getByName(cv.getDataString());
792
793        if (oblockStatus == null) {
794            throw new InvalidConditionalVariableException(
795                    Bundle.getMessage("ConditionalBadOBlockDataString", cv.getDataString()));
796        }
797
798        expression.getSelectNamedBean().setNamedBean(b);
799        expression.setBeanState(oblockStatus);
800
801        return expression;
802    }
803
804
805    private DigitalActionBean getSensorAction(@Nonnull ConditionalAction ca, Sensor sn, String reference) throws JmriException {
806
807        switch (ca.getType()) {
808            case SET_SENSOR:
809                ActionSensor action =
810                        new ActionSensor(InstanceManager.getDefault(DigitalActionManager.class)
811                                .getAutoSystemName(), null);
812
813                if (reference != null) {
814                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
815                    action.getSelectNamedBean().setReference(reference);
816                } else {
817                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
818                    action.getSelectNamedBean().setNamedBean(sn);
819                }
820
821                switch (ca.getActionData()) {
822                    case jmri.Route.TOGGLE:
823                        action.getSelectEnum().setEnum(ActionSensor.SensorState.Toggle);
824                        break;
825
826                    case Sensor.INACTIVE:
827                        action.getSelectEnum().setEnum(ActionSensor.SensorState.Inactive);
828                        break;
829
830                    case Sensor.ACTIVE:
831                        action.getSelectEnum().setEnum(ActionSensor.SensorState.Active);
832                        break;
833
834                    default:
835                        throw new InvalidConditionalVariableException(
836                                Bundle.getMessage("ActionBadSensorState", ca.getActionData()));
837                }
838                return action;
839
840            case RESET_DELAYED_SENSOR:
841            case DELAYED_SENSOR:
842                ConditionalAction caTemp = new DefaultConditionalAction();
843                caTemp.setType(Conditional.Action.SET_SENSOR);
844                caTemp.setActionData(ca.getActionData());
845                DigitalActionBean subAction = getSensorAction(caTemp, sn, reference);
846                ExecuteDelayed delayedAction =
847                        new ExecuteDelayed(InstanceManager.getDefault(DigitalActionManager.class)
848                                .getAutoSystemName(), null);
849
850                String sNumber = ca.getActionString();
851                try {
852                    int time = Integer.parseInt(sNumber);
853                    delayedAction.setDelay(time);
854                    delayedAction.setUnit(TimerUnit.Seconds);
855                } catch (NumberFormatException e) {
856                    try {
857                        float time = Float.parseFloat(sNumber);
858                        delayedAction.setDelay((int) (time * 1000));
859                        delayedAction.setUnit(TimerUnit.MilliSeconds);
860                    } catch (NumberFormatException e2) {
861                        // If here, assume that sNumber has the name of a memory.
862                        // Logix supports this memory to have a floating point value
863                        // but LogixNG requires this memory to have an integer value.
864                        if (sNumber.charAt(0) == '@') {
865                            sNumber = sNumber.substring(1);
866                        }
867                        delayedAction.setDelayAddressing(NamedBeanAddressing.Reference);
868                        delayedAction.setDelayReference("{" + sNumber + "}");
869                        delayedAction.setUnit(TimerUnit.Seconds);
870                    }
871                }
872
873                delayedAction.setResetIfAlreadyStarted(ca.getType() == Conditional.Action.RESET_DELAYED_SENSOR);
874                if (!_dryRun) {
875                    MaleSocket subActionSocket = InstanceManager.getDefault(DigitalActionManager.class)
876                            .registerAction(subAction);
877                    delayedAction.getChild(0).connect(subActionSocket);
878                }
879                return delayedAction;
880
881            case CANCEL_SENSOR_TIMERS:
882            default:
883                throw new InvalidConditionalVariableException(
884                        Bundle.getMessage("ActionBadSensorType", ca.getType().toString()));
885        }
886    }
887
888
889    private DigitalActionBean getTurnoutAction(@Nonnull ConditionalAction ca, Turnout tn, String reference) throws JmriException {
890
891        ActionTurnout action;
892
893        switch (ca.getType()) {
894            case SET_TURNOUT:
895                action = new ActionTurnout(InstanceManager.getDefault(DigitalActionManager.class)
896                                .getAutoSystemName(), null);
897
898                if (reference != null) {
899                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
900                    action.getSelectNamedBean().setReference(reference);
901                } else {
902                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
903                    action.getSelectNamedBean().setNamedBean(tn);
904                }
905
906                switch (ca.getActionData()) {
907                    case jmri.Route.TOGGLE:
908                        action.getSelectEnum().setEnum(ActionTurnout.TurnoutState.Toggle);
909                        break;
910
911                    case Turnout.CLOSED:
912                        action.getSelectEnum().setEnum(ActionTurnout.TurnoutState.Closed);
913                        break;
914
915                    case Turnout.THROWN:
916                        action.getSelectEnum().setEnum(ActionTurnout.TurnoutState.Thrown);
917                        break;
918
919                    default:
920                        throw new InvalidConditionalVariableException(
921                                Bundle.getMessage("ActionBadTurnoutState", ca.getActionData()));
922                }
923                break;
924
925            case RESET_DELAYED_TURNOUT:
926            case DELAYED_TURNOUT:
927                ConditionalAction caTemp = new DefaultConditionalAction();
928                caTemp.setType(Conditional.Action.SET_TURNOUT);
929                caTemp.setActionData(ca.getActionData());
930                DigitalActionBean subAction = getTurnoutAction(caTemp, tn, reference);
931                ExecuteDelayed delayedAction =
932                        new ExecuteDelayed(InstanceManager.getDefault(DigitalActionManager.class)
933                                .getAutoSystemName(), null);
934
935                String sNumber = ca.getActionString();
936                try {
937                    int time = Integer.parseInt(sNumber);
938                    delayedAction.setDelay(time);
939                    delayedAction.setUnit(TimerUnit.Seconds);
940                } catch (NumberFormatException e) {
941                    try {
942                        float time = Float.parseFloat(sNumber);
943                        delayedAction.setDelay((int) (time * 1000));
944                        delayedAction.setUnit(TimerUnit.MilliSeconds);
945                    } catch (NumberFormatException e2) {
946                        // If here, assume that sNumber has the name of a memory.
947                        // Logix supports this memory to have a floating point value
948                        // but LogixNG requires this memory to have an integer value.
949                        if (sNumber.charAt(0) == '@') {
950                            sNumber = sNumber.substring(1);
951                        }
952                        delayedAction.setDelayAddressing(NamedBeanAddressing.Reference);
953                        delayedAction.setDelayReference("{" + sNumber + "}");
954                        delayedAction.setUnit(TimerUnit.Seconds);
955                    }
956                }
957
958                delayedAction.setResetIfAlreadyStarted(ca.getType() == Conditional.Action.RESET_DELAYED_TURNOUT);
959                if (!_dryRun) {
960                    MaleSocket subActionSocket = InstanceManager.getDefault(DigitalActionManager.class)
961                            .registerAction(subAction);
962                    delayedAction.getChild(0).connect(subActionSocket);
963                }
964                return delayedAction;
965
966            case LOCK_TURNOUT:
967                ActionTurnoutLock action2 = new ActionTurnoutLock(InstanceManager.getDefault(DigitalActionManager.class)
968                                .getAutoSystemName(), null);
969
970                if (reference != null) {
971                    action2.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
972                    action2.getSelectNamedBean().setReference(reference);
973                } else {
974                    action2.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
975                    action2.getSelectNamedBean().setNamedBean(tn);
976                }
977
978                switch (ca.getActionData()) {
979                    case jmri.Route.TOGGLE:
980                        action2.getSelectEnum().setEnum(ActionTurnoutLock.TurnoutLock.Toggle);
981                        break;
982
983                    case Turnout.LOCKED:
984                        action2.getSelectEnum().setEnum(ActionTurnoutLock.TurnoutLock.Lock);
985                        break;
986
987                    case Turnout.UNLOCKED:
988                        action2.getSelectEnum().setEnum(ActionTurnoutLock.TurnoutLock.Unlock);
989                        break;
990
991                    default:
992                        throw new InvalidConditionalVariableException(
993                                Bundle.getMessage("ActionBadTurnoutLock", ca.getActionData()));
994                }
995                return action2;
996
997            case CANCEL_TURNOUT_TIMERS:
998            default:
999                throw new InvalidConditionalVariableException(
1000                        Bundle.getMessage("ActionBadTurnoutType", ca.getType().toString()));
1001        }
1002
1003        return action;
1004    }
1005
1006
1007    private DigitalActionBean getMemoryAction(@Nonnull ConditionalAction ca, Memory my, String reference) throws JmriException {
1008
1009        ActionMemory action;
1010
1011        action = new ActionMemory(InstanceManager.getDefault(DigitalActionManager.class)
1012                        .getAutoSystemName(), null);
1013
1014        if (reference != null) {
1015            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1016            action.getSelectNamedBean().setReference(reference);
1017        } else {
1018            action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1019            action.getSelectNamedBean().setNamedBean(my);
1020        }
1021
1022        switch (ca.getType()) {
1023            case SET_MEMORY:
1024                action.setMemoryOperation(ActionMemory.MemoryOperation.SetToString);
1025                action.setOtherConstantValue(ca.getActionString());
1026                break;
1027
1028            case COPY_MEMORY:
1029                action.setMemoryOperation(ActionMemory.MemoryOperation.CopyMemoryToMemory);
1030
1031                // Logix COPY_MEMORY stores data reversed
1032                String fromMemory = ca.getActionString();
1033                if (fromMemory != null && fromMemory.length() > 0 && fromMemory.charAt(0) == '@') {
1034                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Reference);
1035                    action.getSelectNamedBean().setReference("{"+fromMemory.substring(1)+"}");
1036                } else {
1037                    action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1038                    if (fromMemory != null) {
1039                        action.getSelectNamedBean().setNamedBean(fromMemory);
1040                    }
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 = 0;
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 = 0;
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 != null && aspect.length() > 0 && 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 == null || 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 == null || 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 == null || 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 == null || 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 == null || 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 == null || 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 != null && sound.length() > 0 && 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) action.getSelectNamedBean().setNamedBean(audio);
1536        }
1537
1538        switch (ca.getActionData()) {
1539            case Audio.CMD_PLAY:
1540                action.getSelectEnum().setEnum(ActionAudio.Operation.Play);
1541                break;
1542            case Audio.CMD_STOP:
1543                action.getSelectEnum().setEnum(ActionAudio.Operation.Stop);
1544                break;
1545            case Audio.CMD_PLAY_TOGGLE:
1546                action.getSelectEnum().setEnum(ActionAudio.Operation.PlayToggle);
1547                break;
1548            case Audio.CMD_PAUSE:
1549                action.getSelectEnum().setEnum(ActionAudio.Operation.Pause);
1550                break;
1551            case Audio.CMD_RESUME:
1552                action.getSelectEnum().setEnum(ActionAudio.Operation.Resume);
1553                break;
1554            case Audio.CMD_PAUSE_TOGGLE:
1555                action.getSelectEnum().setEnum(ActionAudio.Operation.PauseToggle);
1556                break;
1557            case Audio.CMD_REWIND:
1558                action.getSelectEnum().setEnum(ActionAudio.Operation.Rewind);
1559                break;
1560            case Audio.CMD_FADE_IN:
1561                action.getSelectEnum().setEnum(ActionAudio.Operation.FadeIn);
1562                break;
1563            case Audio.CMD_FADE_OUT:
1564                action.getSelectEnum().setEnum(ActionAudio.Operation.FadeOut);
1565                break;
1566            case Audio.CMD_RESET_POSITION:
1567                action.getSelectEnum().setEnum(ActionAudio.Operation.ResetPosition);
1568                break;
1569            default:
1570                break;
1571        }
1572
1573        return action;
1574    }
1575
1576    private DigitalActionBean getSoundAction(@Nonnull ConditionalAction ca) throws JmriException {
1577        ActionSound action =
1578                new ActionSound(InstanceManager.getDefault(DigitalActionManager.class)
1579                        .getAutoSystemName(), null);
1580
1581        action.getSelectEnum().setAddressing(NamedBeanAddressing.Direct);
1582        action.setSoundAddressing(NamedBeanAddressing.Direct);
1583
1584        String sound = ca.getActionString();
1585        if (sound != null && sound.length() > 0 && sound.charAt(0) == '@') {
1586            action.setSoundAddressing(NamedBeanAddressing.Reference);
1587            action.setSoundReference(sound.substring(1));
1588        } else {
1589            action.setSound(sound);
1590        }
1591
1592        return action;
1593    }
1594
1595    private DigitalActionBean getAudioOrSoundAction(@Nonnull ConditionalAction ca) throws JmriException {
1596        switch (ca.getType()) {
1597            case CONTROL_AUDIO:
1598                return getAudioAction(ca);
1599
1600            case PLAY_SOUND:
1601                return getSoundAction(ca);
1602
1603            default:
1604                throw new InvalidConditionalVariableException(
1605                        Bundle.getMessage("ConditionalBadAudioOrSoundType", ca.getType().toString()));
1606        }
1607    }
1608
1609
1610    private DigitalActionBean getScriptAction(@Nonnull ConditionalAction ca) throws JmriException {
1611        ActionScript action =
1612                new ActionScript(InstanceManager.getDefault(DigitalActionManager.class)
1613                        .getAutoSystemName(), null);
1614
1615        action.setOperationAddressing(NamedBeanAddressing.Direct);
1616        action.setScriptAddressing(NamedBeanAddressing.Direct);
1617
1618        String script = ca.getActionString();
1619        if (script != null && script.length() > 0 && script.charAt(0) == '@') {
1620            action.setScriptAddressing(NamedBeanAddressing.Reference);
1621            action.setScriptReference(script.substring(1));
1622        } else {
1623            action.setScript(script);
1624        }
1625
1626        switch (ca.getType()) {
1627            case RUN_SCRIPT:
1628                action.setOperationType(ActionScript.OperationType.RunScript);
1629                break;
1630
1631            case JYTHON_COMMAND:
1632                action.setOperationType(ActionScript.OperationType.SingleLineCommand);
1633                break;
1634
1635            default:
1636                throw new InvalidConditionalVariableException(
1637                        Bundle.getMessage("ActionBadScriptType", ca.getType().toString()));
1638        }
1639
1640        return action;
1641    }
1642
1643
1644    private DigitalActionBean getRouteAction(@Nonnull ConditionalAction ca, Route b, String reference) throws JmriException {
1645        TriggerRoute action =
1646                new TriggerRoute(InstanceManager.getDefault(DigitalActionManager.class)
1647                        .getAutoSystemName(), null);
1648
1649        action.getSelectNamedBean().setAddressing(NamedBeanAddressing.Direct);
1650        action.getSelectEnum().setAddressing(NamedBeanAddressing.Direct);
1651
1652        String devName = ca.getDeviceName();
1653        if (devName != null) {
1654            if (devName.length() > 0 && devName.charAt(0) == '@') {
1655                String memName = devName.substring(1);
1656                action.getSelectEnum().setAddressing(NamedBeanAddressing.Reference);
1657                action.getSelectEnum().setReference("{" + memName + "}");
1658            } else {
1659                action.getSelectNamedBean().setNamedBean(devName);
1660            }
1661        }
1662
1663        switch (ca.getType()) {
1664            case TRIGGER_ROUTE:
1665                action.getSelectEnum().setEnum(TriggerRoute.Operation.TriggerRoute);
1666                break;
1667
1668            default:
1669                throw new InvalidConditionalVariableException(
1670                        Bundle.getMessage("ActionBadRouteType", ca.getType().toString()));
1671        }
1672
1673        return action;
1674    }
1675
1676
1677    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ImportConditional.class);
1678
1679}