001package jmri.implementation; 002 003import java.awt.event.ActionListener; 004import javax.swing.Timer; 005 006import javax.annotation.CheckForNull; 007import javax.annotation.Nonnull; 008 009import jmri.Audio; 010import jmri.Conditional; 011import jmri.ConditionalAction; 012import jmri.InstanceManager; 013import jmri.Light; 014import jmri.Memory; 015import jmri.NamedBean; 016import jmri.NamedBeanHandle; 017import jmri.Route; 018import jmri.RouteManager; 019import jmri.Sensor; 020import jmri.SignalHead; 021import jmri.Turnout; 022import jmri.jmrit.Sound; 023import jmri.jmrit.beantable.LogixTableAction; 024import jmri.jmrit.logix.OBlockManager; 025import jmri.jmrit.logix.Warrant; 026import jmri.jmrit.logix.WarrantManager; 027 028/** 029 * The consequent of the antecedent of the conditional proposition. The data for 030 * the action to be taken when a Conditional calculates to True 031 * <p> 032 * This is in the implementations package because of a Swing dependence via the 033 * times. Java 1.5 or Java 1.6 might make it possible to break that, which will 034 * simplify things. 035 * 036 * @author Pete Cressman Copyright (C) 2009, 2010, 2011 037 * @author Matthew Harris copyright (c) 2009 038 */ 039public class DefaultConditionalAction implements ConditionalAction { 040 041 private int _option = Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE; 042 private Conditional.Action _type = Conditional.Action.NONE; 043 private String _deviceName = " "; 044 private int _actionData = 0; 045 private String _actionString = ""; 046 private NamedBeanHandle<?> _namedBean = null; 047 048 private Timer _timer = null; 049 private ActionListener _listener = null; 050 private boolean _timerActive = false; 051 private boolean _indirectAction = false; 052 private Sound _sound = null; 053 054 static final java.util.ResourceBundle rbx = java.util.ResourceBundle.getBundle("jmri.jmrit.conditional.ConditionalBundle"); 055 private final jmri.NamedBeanHandleManager nbhm = InstanceManager.getDefault(jmri.NamedBeanHandleManager.class); 056 057 public DefaultConditionalAction() { 058 } 059 060 public DefaultConditionalAction( int option, @Nonnull Conditional.Action type, 061 String name, int actionData, String actionStr ) { 062 _option = option; 063 _type = type; 064 _deviceName = name; 065 _actionData = actionData; 066 _actionString = actionStr; 067 068 NamedBean bean = getIndirectBean(_deviceName); 069 if (bean == null) { 070 bean = getActionBean(_deviceName); 071 } 072 if (bean != null) { 073 _namedBean = nbhm.getNamedBeanHandle(_deviceName, bean); 074 } else { 075 _namedBean = null; 076 } 077 } 078 079 @Override 080 public boolean equals(Object obj) { 081 if (obj == this) { 082 return true; 083 } 084 if (obj == null) { 085 return false; 086 } 087 088 if (getClass() != obj.getClass()) { 089 return false; 090 } else { 091 DefaultConditionalAction p = (DefaultConditionalAction) obj; 092 if ((p.getOption() != this.getOption()) 093 || (p.getType() != this.getType()) 094 || (p.getActionData() != this.getActionData())) { 095 return false; 096 } 097 098 if ((p._namedBean == null && this._namedBean != null) 099 || (p._namedBean != null && this._namedBean == null) 100 || (p._namedBean != null && this._namedBean != null && !p._namedBean.equals(this._namedBean))) { 101 return false; 102 } 103 104 if ((p._deviceName == null && this._deviceName != null) 105 || (p._deviceName != null && this._deviceName == null) 106 || (p._deviceName != null && this._deviceName != null && !p._deviceName.equals(this._deviceName))) { 107 return false; 108 } 109 110 if ((p._actionString == null && this._actionString != null) 111 || (p._actionString != null && this._actionString == null) 112 || (p._actionString != null && this._actionString != null && !p._actionString.equals(this._actionString))) { 113 return false; 114 } 115 116 } 117 return true; 118 } 119 120 @Override 121 public int hashCode() { 122 int hash = _option * 1000 + _type.getIntValue() * 1000 * 1000 + _actionData; 123 if (_deviceName != null) { 124 hash += _deviceName.hashCode(); 125 } 126 return hash; 127 } 128 129 /** 130 * If this is an indirect reference, return the Memory bean. 131 * 132 */ 133 @CheckForNull 134 private Memory getIndirectBean(@CheckForNull String devName) { 135 if (devName != null && devName.length() > 0 && devName.charAt(0) == '@') { 136 String memName = devName.substring(1); 137 Memory m = InstanceManager.memoryManagerInstance().getMemory(memName); 138 if (m != null) { 139 _indirectAction = true; 140 return m; 141 } 142 log.error("\"{}\" invalid indirect memory name in action {} of type {}", devName, _actionString, _type); 143 } else { 144 _indirectAction = false; 145 } 146 return null; 147 } 148 149 /** 150 * Return the device bean that will do the action. 151 * 152 */ 153 @CheckForNull 154 private NamedBean getActionBean(@CheckForNull String devName) { 155 if (devName == null) { 156 return null; 157 } 158 NamedBean bean = null; 159 try { 160 switch (_type.getItemType()) { 161 case SENSOR: 162 try { 163 bean = InstanceManager.sensorManagerInstance().provideSensor(devName); 164 } catch (IllegalArgumentException e) { 165 bean = null; 166 log.error("invalid sensor name= \"{}\" in conditional action", devName); 167 } 168 break; 169 case TURNOUT: 170 try { 171 bean = InstanceManager.turnoutManagerInstance().provideTurnout(devName); 172 } catch (IllegalArgumentException e) { 173 bean = null; 174 log.error("invalid turnout name= \"{}\" in conditional action", devName); 175 } 176 break; 177 case MEMORY: 178 try { 179 bean = InstanceManager.memoryManagerInstance().provideMemory(devName); 180 } catch (IllegalArgumentException e) { 181 bean = null; 182 log.error("invalid memory name= \"{}\" in conditional action", devName); 183 } 184 break; 185 case LIGHT: 186 try { 187 bean = InstanceManager.lightManagerInstance().getLight(devName); 188 } catch (IllegalArgumentException e) { 189 bean = null; 190 log.error("invalid light name= \"{}\" in conditional action", devName); 191 } 192 break; 193 case SIGNALMAST: 194 try { 195 bean = InstanceManager.getDefault(jmri.SignalMastManager.class).provideSignalMast(devName); 196 } catch (IllegalArgumentException e) { 197 bean = null; 198 log.error("invalid signal mast name= \"{}\" in conditional action", devName); 199 } 200 break; 201 case SIGNALHEAD: 202 try { 203 bean = InstanceManager.getDefault(jmri.SignalHeadManager.class).getSignalHead(devName); 204 } catch (IllegalArgumentException e) { 205 bean = null; 206 log.error("invalid signal head name= \"{}\" in conditional action", devName); 207 } 208 break; 209 case WARRANT: 210 try { 211 bean = InstanceManager.getDefault(WarrantManager.class).getWarrant(devName); 212 } catch (IllegalArgumentException e) { 213 bean = null; 214 log.error("invalid Warrant name= \"{}\" in conditional action", devName); 215 } 216 break; 217 case OBLOCK: 218 try { 219 bean = InstanceManager.getDefault(OBlockManager.class).getOBlock(devName); 220 } catch (IllegalArgumentException e) { 221 bean = null; 222 log.error("invalid OBlock name= \"{}\" in conditional action", devName); 223 } 224 break; 225 case ENTRYEXIT: 226 try { 227 bean = InstanceManager.getDefault(jmri.jmrit.entryexit.EntryExitPairs.class).getNamedBean(devName); 228 } catch (IllegalArgumentException e) { 229 bean = null; 230 log.error("invalid NX name= \"{}\" in conditional action", devName); 231 } 232 break; 233 case LOGIX: 234 try { 235 bean = InstanceManager.getDefault(jmri.LogixManager.class).getLogix(devName); 236 } catch (IllegalArgumentException e) { 237 bean = null; 238 log.error("invalid Logix name= \"{}\" in conditional action", devName); 239 } 240 break; 241 default: 242 if (getType() == Conditional.Action.TRIGGER_ROUTE) { 243 try { 244 bean = InstanceManager.getDefault(RouteManager.class).getRoute(devName); 245 } catch (IllegalArgumentException e) { 246 bean = null; 247 log.error("invalid Route name= \"{}\" in conditional action", devName); 248 } 249 } 250 } 251 } catch (java.lang.NumberFormatException ex) { 252 // ingonred, can be considered normal if the logixs are loaded prior to any other beans 253 } 254 return bean; 255 } 256 257 /** 258 * The consequent device or element type. 259 */ 260 @Override 261 @Nonnull 262 public Conditional.Action getType() { 263 return _type; 264 } 265 266 @Override 267 public void setType(@Nonnull Conditional.Action type) { 268 _type = type; 269 } 270 271 /** 272 * Set type from user name for it. 273 */ 274 @Override 275 public void setType(String type) { 276 _type = stringToActionType(type); 277 } 278 279 /** 280 * Name of the device or element that is affected. 281 */ 282 @Override 283 public String getDeviceName() { 284 if (_namedBean != null) { 285 return _namedBean.getName(); 286 } 287 /* As we have a trigger for something using the action, then hopefully 288 all the managers have been loaded and we can get the bean, which prevented 289 the bean from being loaded in the first place */ 290 setDeviceName(_deviceName); 291 return _deviceName; 292 } 293 294 @Override 295 public void setDeviceName(String deviceName) { 296 _deviceName = deviceName; 297 NamedBean bean = getIndirectBean(_deviceName); 298 if (bean == null) { 299 bean = getActionBean(_deviceName); 300 } 301 if (bean != null) { 302 _namedBean = nbhm.getNamedBeanHandle(_deviceName, bean); 303 } else { 304 _namedBean = null; 305 } 306 } 307 308 @Override 309 @CheckForNull 310 public NamedBeanHandle<?> getNamedBean() { 311 if (_indirectAction) { 312 Memory m = (Memory) (_namedBean.getBean()); 313 String actionName = (String) m.getValue(); 314 NamedBean bean = getActionBean(actionName); 315 if (bean != null) { 316 return nbhm.getNamedBeanHandle(actionName, bean); 317 } else { 318 return null; 319 } 320 } 321 return _namedBean; 322 } 323 324 @Override 325 @CheckForNull 326 public NamedBean getBean() { 327 NamedBean x = beanFromHandle(); 328 if (x != null) { 329 return x; 330 } 331 setDeviceName(_deviceName); //ReApply name as that will create namedBean, save replicating it here 332 return beanFromHandle(); 333 } 334 335 @CheckForNull 336 private NamedBean beanFromHandle(){ 337 var handle = getNamedBean(); 338 if (handle != null) { 339 return handle.getBean(); 340 } 341 return null; 342 } 343 344 /** 345 * Options on when action is taken. 346 */ 347 @Override 348 public int getOption() { 349 return _option; 350 } 351 352 @Override 353 public void setOption(int option) { 354 _option = option; 355 } 356 357 /** 358 * Integer data for action. 359 */ 360 @Override 361 public int getActionData() { 362 return _actionData; 363 } 364 365 @Override 366 public void setActionData(int actionData) { 367 _actionData = actionData; 368 } 369 370 /** 371 * Set action data from I18N name for it. 372 */ 373 @Override 374 public void setActionData(String actionData) { 375 _actionData = stringToActionData(actionData); 376 } 377 378 /** 379 * String data for action. 380 */ 381 @Nonnull 382 @Override 383 public String getActionString() { 384 if (_actionString == null) { 385 _actionString = getTypeString(); 386 } 387 return _actionString; 388 } 389 390 @Override 391 public void setActionString(String actionString) { 392 _actionString = actionString; 393 } 394 395 /* 396 * Get timer for delays and other timed events. 397 */ 398 @Override 399 @CheckForNull 400 public Timer getTimer() { 401 return _timer; 402 } 403 404 /* 405 * Set timer for delays and other timed events. 406 */ 407 @Override 408 public void setTimer(Timer timer) { 409 _timer = timer; 410 } 411 412 @Override 413 public boolean isTimerActive() { 414 return _timerActive; 415 } 416 417 @Override 418 public void startTimer() { 419 if (_timer != null) { 420 _timer.start(); 421 _timerActive = true; 422 } else { 423 log.error("timer is null for {} of type {}", _deviceName, getTypeString()); 424 } 425 } 426 427 @Override 428 public void stopTimer() { 429 if (_timer != null) { 430 _timer.stop(); 431 _timerActive = false; 432 } 433 } 434 435 /* 436 * Set listener for delays and other timed events. 437 */ 438 @Override 439 @CheckForNull 440 public ActionListener getListener() { 441 return _listener; 442 } 443 444 /* 445 * set listener for delays and other timed events 446 */ 447 @Override 448 public void setListener(ActionListener listener) { 449 _listener = listener; 450 } 451 452 /** 453 * Get Sound file. 454 */ 455 @Override 456 @CheckForNull 457 public Sound getSound() { 458 return _sound; 459 } 460 461 /** 462 * Set the sound file. 463 * 464 * @param sound the new sound file 465 */ 466 protected void setSound(Sound sound) { 467 _sound = sound; 468 } 469 470 /* 471 * Methods that return user interface strings **** 472 */ 473 474 /** 475 * @return name of this consequent type 476 */ 477 @Nonnull 478 @Override 479 public String getTypeString() { 480 return _type.toString(); 481 } 482 483 /** 484 * @return name of the option for this consequent type 485 */ 486 @Nonnull 487 @Override 488 public String getOptionString(boolean type) { 489 return getOptionString(_option, type); 490 } 491 492 @Nonnull 493 @Override 494 public String getActionDataString() { 495 return getActionDataString(_type, _actionData); 496 } 497 498 /** 499 * Convert Variable Type to Text String. 500 * 501 * @.param t the Action type 502 * @.return a human readable description of the type or an empty String 503 *./ 504 public static String getItemTypeString(int t) { 505 switch (t) { 506 case Conditional.ITEM_TYPE_SENSOR: 507 return (Bundle.getMessage("BeanNameSensor")); 508 case Conditional.ITEM_TYPE_TURNOUT: 509 return (Bundle.getMessage("BeanNameTurnout")); 510 case Conditional.ITEM_TYPE_LIGHT: 511 return (Bundle.getMessage("BeanNameLight")); 512 case Conditional.ITEM_TYPE_SIGNALHEAD: 513 return (Bundle.getMessage("BeanNameSignalHead")); 514 case Conditional.ITEM_TYPE_SIGNALMAST: 515 return (Bundle.getMessage("BeanNameSignalMast")); 516 case Conditional.ITEM_TYPE_MEMORY: 517 return (Bundle.getMessage("BeanNameMemory")); 518 case Conditional.ITEM_TYPE_LOGIX: 519 return (Bundle.getMessage("BeanNameLogix")); 520 case Conditional.ITEM_TYPE_WARRANT: 521 return (Bundle.getMessage("BeanNameWarrant")); 522 case Conditional.ITEM_TYPE_OBLOCK: 523 return (Bundle.getMessage("BeanNameOBlock")); 524 case Conditional.ITEM_TYPE_ENTRYEXIT: 525 return (Bundle.getMessage("BeanNameEntryExit")); 526 case Conditional.ITEM_TYPE_CLOCK: 527 return (Bundle.getMessage("FastClock")); 528 case Conditional.ITEM_TYPE_AUDIO: 529 return (Bundle.getMessage("BeanNameAudio")); 530 case Conditional.ITEM_TYPE_SCRIPT: 531 return (Bundle.getMessage("Script")); 532 case Conditional.ITEM_TYPE_OTHER: 533 return (rbx.getString("Other")); 534 default: 535 // fall through 536 break; 537 } 538 return ""; 539 } 540*/ 541 /** 542 * Convert Consequent Type to text String. 543 * 544 * @.param t the Action type 545 * @.return a human readable description of the type or an empty String 546 *./ 547 public static String getActionTypeString(int t) { 548 switch (t) { 549 case Conditional.ACTION_NONE: 550 return (rbx.getString("ActionNone")); 551 case Conditional.ACTION_SET_TURNOUT: 552 return (rbx.getString("ActionSetTurnout")); 553 case Conditional.ACTION_SET_SIGNAL_APPEARANCE: 554 return (rbx.getString("ActionSetSignal")); 555 case Conditional.ACTION_SET_SIGNAL_HELD: 556 return (rbx.getString("ActionSetSignalHeld")); 557 case Conditional.ACTION_CLEAR_SIGNAL_HELD: 558 return (rbx.getString("ActionClearSignalHeld")); 559 case Conditional.ACTION_SET_SIGNAL_DARK: 560 return (rbx.getString("ActionSetSignalDark")); 561 case Conditional.ACTION_SET_SIGNAL_LIT: 562 return (rbx.getString("ActionSetSignalLit")); 563 case Conditional.ACTION_TRIGGER_ROUTE: 564 return (rbx.getString("ActionTriggerRoute")); 565 case Conditional.ACTION_SET_SENSOR: 566 return (rbx.getString("ActionSetSensor")); 567 case Conditional.ACTION_DELAYED_SENSOR: 568 return (rbx.getString("ActionDelayedSensor")); 569 case Conditional.ACTION_SET_LIGHT: 570 return (rbx.getString("ActionSetLight")); 571 case Conditional.ACTION_SET_MEMORY: 572 return (rbx.getString("ActionSetMemory")); 573 case Conditional.ACTION_ENABLE_LOGIX: 574 return (rbx.getString("ActionEnableLogix")); 575 case Conditional.ACTION_DISABLE_LOGIX: 576 return (rbx.getString("ActionDisableLogix")); 577 case Conditional.ACTION_PLAY_SOUND: 578 return (rbx.getString("ActionPlaySound")); 579 case Conditional.ACTION_RUN_SCRIPT: 580 return (rbx.getString("ActionRunScript")); 581 case Conditional.ACTION_DELAYED_TURNOUT: 582 return (rbx.getString("ActionDelayedTurnout")); 583 case Conditional.ACTION_LOCK_TURNOUT: 584 return (rbx.getString("ActionTurnoutLock")); 585 case Conditional.ACTION_RESET_DELAYED_SENSOR: 586 return (rbx.getString("ActionResetDelayedSensor")); 587 case Conditional.ACTION_CANCEL_SENSOR_TIMERS: 588 return (rbx.getString("ActionCancelSensorTimers")); 589 case Conditional.ACTION_RESET_DELAYED_TURNOUT: 590 return (rbx.getString("ActionResetDelayedTurnout")); 591 case Conditional.ACTION_CANCEL_TURNOUT_TIMERS: 592 return (rbx.getString("ActionCancelTurnoutTimers")); 593 case Conditional.ACTION_SET_FAST_CLOCK_TIME: 594 return (rbx.getString("ActionSetFastClockTime")); 595 case Conditional.ACTION_START_FAST_CLOCK: 596 return (rbx.getString("ActionStartFastClock")); 597 case Conditional.ACTION_STOP_FAST_CLOCK: 598 return (rbx.getString("ActionStopFastClock")); 599 case Conditional.ACTION_COPY_MEMORY: 600 return (rbx.getString("ActionCopyMemory")); 601 case Conditional.ACTION_SET_LIGHT_INTENSITY: 602 return (rbx.getString("ActionSetLightIntensity")); 603 case Conditional.ACTION_SET_LIGHT_TRANSITION_TIME: 604 return (rbx.getString("ActionSetLightTransitionTime")); 605 case Conditional.ACTION_CONTROL_AUDIO: 606 return (rbx.getString("ActionControlAudio")); 607 case Conditional.ACTION_JYTHON_COMMAND: 608 return (rbx.getString("ActionJythonCommand")); 609 case Conditional.ACTION_ALLOCATE_WARRANT_ROUTE: 610 return (rbx.getString("ActionAllocateWarrant")); 611 case Conditional.ACTION_DEALLOCATE_WARRANT_ROUTE: 612 return (rbx.getString("ActionDeallocateWarrant")); 613 case Conditional.ACTION_SET_ROUTE_TURNOUTS: 614 return (rbx.getString("ActionSetWarrantTurnouts")); 615 case Conditional.ACTION_AUTO_RUN_WARRANT: 616 return (rbx.getString("ActionAutoRunWarrant")); 617 case Conditional.ACTION_MANUAL_RUN_WARRANT: 618 return (rbx.getString("ActionManualRunWarrant")); 619 case Conditional.ACTION_CONTROL_TRAIN: 620 return (rbx.getString("ActionControlTrain")); 621 case Conditional.ACTION_SET_TRAIN_ID: 622 return (rbx.getString("ActionSetTrainId")); 623 case Conditional.ACTION_SET_TRAIN_NAME: 624 return (rbx.getString("ActionSetTrainName")); 625 case Conditional.ACTION_SET_SIGNALMAST_ASPECT: 626 return (rbx.getString("ActionSetSignalMastAspect")); 627 case Conditional.ACTION_THROTTLE_FACTOR: 628 return (rbx.getString("ActionSetThrottleFactor")); 629 case Conditional.ACTION_SET_SIGNALMAST_HELD: 630 return (rbx.getString("ActionSetSignalMastHeld")); 631 case Conditional.ACTION_CLEAR_SIGNALMAST_HELD: 632 return (rbx.getString("ActionClearSignalMastHeld")); 633 case Conditional.ACTION_SET_SIGNALMAST_DARK: 634 return (rbx.getString("ActionSetSignalMastDark")); 635 case Conditional.ACTION_SET_SIGNALMAST_LIT: 636 return (rbx.getString("ActionClearSignalMastDark")); 637 case Conditional.ACTION_SET_BLOCK_VALUE: 638 return (rbx.getString("ActionSetBlockValue")); 639 case Conditional.ACTION_SET_BLOCK_ERROR: 640 return (rbx.getString("ActionSetBlockError")); 641 case Conditional.ACTION_CLEAR_BLOCK_ERROR: 642 return (rbx.getString("ActionClearBlockError")); 643 case Conditional.ACTION_DEALLOCATE_BLOCK: 644 return (rbx.getString("ActionDeallocateBlock")); 645 case Conditional.ACTION_SET_BLOCK_OUT_OF_SERVICE: 646 return (rbx.getString("ActionSetBlockOutOfService")); 647 case Conditional.ACTION_SET_BLOCK_IN_SERVICE: 648 return (rbx.getString("ActionBlockInService")); 649 case Conditional.ACTION_SET_NXPAIR_ENABLED: 650 return (rbx.getString("ActionNXPairEnabled")); 651 case Conditional.ACTION_SET_NXPAIR_DISABLED: 652 return (rbx.getString("ActionNXPairDisabled")); 653 case Conditional.ACTION_SET_NXPAIR_SEGMENT: 654 return (rbx.getString("ActionNXPairSegment")); 655 default: 656 // fall through 657 break; 658 } 659 log.warn("Unexpected parameter to getActionTypeString({})", t); 660 return (""); 661 } 662*/ 663 /** 664 * Convert consequent option to I18N String. 665 * 666 * @param opt the option. 667 * @param type true if option is a change; false if option is a trigger. 668 * @return a human readable description of the option or an empty String. 669 */ 670 @Nonnull 671 public static String getOptionString(int opt, boolean type) { 672 switch (opt) { 673 case Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE: 674 if (type) { 675 return (rbx.getString("OnChangeToTrue")); 676 } else { 677 return (rbx.getString("OnTriggerToTrue")); 678 } 679 case Conditional.ACTION_OPTION_ON_CHANGE_TO_FALSE: 680 if (type) { 681 return (rbx.getString("OnChangeToFalse")); 682 } else { 683 return (rbx.getString("OnTriggerToFalse")); 684 } 685 case Conditional.ACTION_OPTION_ON_CHANGE: 686 if (type) { 687 return (rbx.getString("OnChange")); 688 } else { 689 return (rbx.getString("OnTrigger")); 690 } 691 default: 692 // fall through 693 break; 694 } 695 log.warn("Unexpected parameter to getOptionString({})", opt); 696 return ""; 697 } 698 699 /** 700 * Get action type from a String. 701 * 702 * @param str the string to get the type for 703 * @return the type or 0 if str is not a recognized action 704 */ 705 @Nonnull 706 public static Conditional.Action stringToActionType(@CheckForNull String str) { 707 if (str != null) { 708 for (Conditional.Action action : Conditional.Action.values()) { 709 if (str.equals(action.toString())) { 710 return action; 711 } 712 } 713 } 714 log.warn("Unexpected parameter to stringToActionType({})", str); 715 return Conditional.Action.NONE; 716 } 717 718 /** 719 * Get action Data from an I18N String. 720 * 721 * @param str the I18N string to get the action data for. 722 * @return the action data of -1 is str is not recognized. 723 */ 724 public static int stringToActionData(@Nonnull String str) { 725 if (str.equals(Bundle.getMessage("TurnoutStateClosed"))) { 726 return Turnout.CLOSED; 727 } else if (str.equals(Bundle.getMessage("TurnoutStateThrown"))) { 728 return Turnout.THROWN; 729 } else if (str.equals(Bundle.getMessage("SensorStateActive"))) { 730 return Sensor.ACTIVE; 731 } else if (str.equals(Bundle.getMessage("SensorStateInactive"))) { 732 return Sensor.INACTIVE; 733 } else if (str.equals(rbx.getString("LightOn"))) { 734 return Light.ON; 735 } else if (str.equals(rbx.getString("LightOff"))) { 736 return Light.OFF; 737 } else if (str.equals(rbx.getString("TurnoutUnlock"))) { 738 return Turnout.UNLOCKED; 739 } else if (str.equals(rbx.getString("TurnoutLock"))) { 740 return Turnout.LOCKED; 741 } else if (str.equals(Bundle.getMessage("SignalHeadStateRed"))) { 742 return SignalHead.RED; 743 } else if (str.equals(Bundle.getMessage("SignalHeadStateYellow"))) { 744 return SignalHead.YELLOW; 745 } else if (str.equals(Bundle.getMessage("SignalHeadStateGreen"))) { 746 return SignalHead.GREEN; 747 } else if (str.equals(Bundle.getMessage("SignalHeadStateDark"))) { 748 return SignalHead.DARK; 749 } else if (str.equals(Bundle.getMessage("SignalHeadStateFlashingRed"))) { 750 return SignalHead.FLASHRED; 751 } else if (str.equals(Bundle.getMessage("SignalHeadStateFlashingYellow"))) { 752 return SignalHead.FLASHYELLOW; 753 } else if (str.equals(Bundle.getMessage("SignalHeadStateFlashingGreen"))) { 754 return SignalHead.FLASHGREEN; 755 } else if (str.equals(Bundle.getMessage("SignalHeadStateLunar"))) { 756 return SignalHead.LUNAR; 757 } else if (str.equals(Bundle.getMessage("SignalHeadStateFlashingLunar"))) { 758 return SignalHead.FLASHLUNAR; 759 } else if (str.equals(rbx.getString("AudioSourcePlay"))) { 760 return Audio.CMD_PLAY; 761 } else if (str.equals(rbx.getString("AudioSourceStop"))) { 762 return Audio.CMD_STOP; 763 } else if (str.equals(rbx.getString("AudioSourcePlayToggle"))) { 764 return Audio.CMD_PLAY_TOGGLE; 765 } else if (str.equals(rbx.getString("AudioSourcePause"))) { 766 return Audio.CMD_PAUSE; 767 } else if (str.equals(rbx.getString("AudioSourceResume"))) { 768 return Audio.CMD_RESUME; 769 } else if (str.equals(rbx.getString("AudioSourcePauseToggle"))) { 770 return Audio.CMD_PAUSE_TOGGLE; 771 } else if (str.equals(rbx.getString("AudioSourceRewind"))) { 772 return Audio.CMD_REWIND; 773 } else if (str.equals(rbx.getString("AudioSourceFadeIn"))) { 774 return Audio.CMD_FADE_IN; 775 } else if (str.equals(rbx.getString("AudioSourceFadeOut"))) { 776 return Audio.CMD_FADE_OUT; 777 } else if (str.equals(rbx.getString("AudioResetPosition"))) { 778 return Audio.CMD_RESET_POSITION; 779 } 780 // empty strings can occur frequently with types that have no integer data 781 if (str.length() > 0) { 782 log.warn("Unexpected parameter to stringToActionData({})", str); 783 } 784 return -1; 785 } 786 787 /** 788 * Get the Action Data String in I18N form. 789 * @param t the Condition.Action, must be null. 790 * @param data the constant for the action command type. 791 * @return the action / data string. 792 */ 793 @Nonnull 794 public static String getActionDataString(@Nonnull Conditional.Action t, int data) { 795 switch (t) { 796 case SET_TURNOUT: 797 case DELAYED_TURNOUT: 798 case RESET_DELAYED_TURNOUT: 799 switch (data) { 800 case Turnout.CLOSED: 801 return (Bundle.getMessage("TurnoutStateClosed")); 802 case Turnout.THROWN: 803 return (Bundle.getMessage("TurnoutStateThrown")); 804 case Route.TOGGLE: 805 return (Bundle.getMessage("Toggle")); 806 default: 807 break; 808 } 809 break; 810 case SET_SIGNAL_APPEARANCE: 811 return DefaultSignalHead.getDefaultStateName(data); 812 case SET_SENSOR: 813 case DELAYED_SENSOR: 814 case RESET_DELAYED_SENSOR: 815 switch (data) { 816 case Sensor.ACTIVE: 817 return (Bundle.getMessage("SensorStateActive")); 818 case Sensor.INACTIVE: 819 return (Bundle.getMessage("SensorStateInactive")); 820 case Route.TOGGLE: 821 return (Bundle.getMessage("Toggle")); 822 default: 823 break; 824 } 825 break; 826 case SET_LIGHT: 827 switch (data) { 828 case Light.ON: 829 return (rbx.getString("LightOn")); 830 case Light.OFF: 831 return (rbx.getString("LightOff")); 832 case Route.TOGGLE: 833 return (Bundle.getMessage("Toggle")); 834 default: 835 break; 836 } 837 break; 838 case LOCK_TURNOUT: 839 switch (data) { 840 case Turnout.UNLOCKED: 841 return (rbx.getString("TurnoutUnlock")); 842 case Turnout.LOCKED: 843 return (rbx.getString("TurnoutLock")); 844 case Route.TOGGLE: 845 return (Bundle.getMessage("Toggle")); 846 default: 847 break; 848 } 849 break; 850 case CONTROL_AUDIO: 851 switch (data) { 852 case Audio.CMD_PLAY: 853 return (rbx.getString("AudioSourcePlay")); 854 case Audio.CMD_STOP: 855 return (rbx.getString("AudioSourceStop")); 856 case Audio.CMD_PLAY_TOGGLE: 857 return (rbx.getString("AudioSourcePlayToggle")); 858 case Audio.CMD_PAUSE: 859 return (rbx.getString("AudioSourcePause")); 860 case Audio.CMD_RESUME: 861 return (rbx.getString("AudioSourceResume")); 862 case Audio.CMD_PAUSE_TOGGLE: 863 return (rbx.getString("AudioSourcePauseToggle")); 864 case Audio.CMD_REWIND: 865 return (rbx.getString("AudioSourceRewind")); 866 case Audio.CMD_FADE_IN: 867 return (rbx.getString("AudioSourceFadeIn")); 868 case Audio.CMD_FADE_OUT: 869 return (rbx.getString("AudioSourceFadeOut")); 870 case Audio.CMD_RESET_POSITION: 871 return (rbx.getString("AudioResetPosition")); 872 default: 873 log.error("Unhandled Audio operation command: {}", data); 874 break; 875 } 876 break; 877 case CONTROL_TRAIN: 878 switch (data) { 879 case Warrant.HALT: 880 return (rbx.getString("WarrantHalt")); 881 case Warrant.RESUME: 882 return (rbx.getString("WarrantResume")); 883 case Warrant.RETRY_FWD: 884 return (rbx.getString("WarrantMoveToNext")); 885 case Warrant.SPEED_UP: 886 return (rbx.getString("WarrantSpeedUp")); 887 case Warrant.STOP: 888 return (rbx.getString("WarrantStop")); 889 case Warrant.ESTOP: 890 return (rbx.getString("WarrantEStop")); 891 case Warrant.ABORT: 892 return (rbx.getString("WarrantAbort")); 893 default: 894 log.error("Unhandled Warrant control: {}", data); 895 } 896 break; 897 default: 898 // fall through 899 break; 900 } 901 return ""; 902 } 903 904 /** 905 * {@inheritDoc } 906 */ 907 @Nonnull 908 @Override 909 public String description(boolean triggerType) { 910 String str = getOptionString(triggerType) + ", " + getTypeString(); 911 if (_deviceName.length() > 0) { 912 switch (_type) { 913 case CANCEL_TURNOUT_TIMERS: 914 case SET_SIGNAL_HELD: 915 case CLEAR_SIGNAL_HELD: 916 case SET_SIGNAL_DARK: 917 case SET_SIGNAL_LIT: 918 case TRIGGER_ROUTE: 919 case CANCEL_SENSOR_TIMERS: 920 case SET_MEMORY: 921 case ENABLE_LOGIX: 922 case DISABLE_LOGIX: 923 case COPY_MEMORY: 924 case SET_LIGHT_INTENSITY: 925 case SET_LIGHT_TRANSITION_TIME: 926 case ALLOCATE_WARRANT_ROUTE: 927 case DEALLOCATE_WARRANT_ROUTE: 928 case SET_SIGNALMAST_HELD: 929 case CLEAR_SIGNALMAST_HELD: 930 case SET_SIGNALMAST_DARK: 931 case SET_SIGNALMAST_LIT: 932 case SET_BLOCK_ERROR: 933 case CLEAR_BLOCK_ERROR: 934 case DEALLOCATE_BLOCK: 935 case SET_BLOCK_OUT_OF_SERVICE: 936 case SET_BLOCK_IN_SERVICE: 937 str = str + ", \"" + _deviceName + "\"."; 938 break; 939 case SET_NXPAIR_ENABLED: 940 case SET_NXPAIR_DISABLED: 941 case SET_NXPAIR_SEGMENT: 942 NamedBean bean = getBean(); 943 str = str + ", \"" + ( bean == null ? "<NULL>" : bean.getUserName() )+ "\"."; 944 break; 945 case SET_ROUTE_TURNOUTS: 946 case AUTO_RUN_WARRANT: 947 case MANUAL_RUN_WARRANT: 948 str = str + " " + rbx.getString("onWarrant") + ", \"" + _deviceName + "\"."; 949 break; 950 case SET_SENSOR: 951 case SET_TURNOUT: 952 case SET_LIGHT: 953 case LOCK_TURNOUT: 954 case RESET_DELAYED_SENSOR: 955 case SET_SIGNAL_APPEARANCE: 956 case RESET_DELAYED_TURNOUT: 957 case DELAYED_TURNOUT: 958 case DELAYED_SENSOR: 959 case CONTROL_AUDIO: 960 str = str + ", \"" + _deviceName + "\" " + rbx.getString("to") 961 + " " + getActionDataString(); 962 break; 963 case GET_TRAIN_LOCATION: 964 case GET_BLOCK_WARRANT: 965 case GET_BLOCK_TRAIN_NAME: 966 str = str + " \"" + _deviceName + "\" " + rbx.getString("intoMemory") 967 + " " + _actionString; 968 break; 969 case SET_SIGNALMAST_ASPECT: 970 str = str + ", \"" + _deviceName + "\" " + rbx.getString("to") 971 + " " + _actionString; 972 break; 973 case CONTROL_TRAIN: 974 str = str + " " + rbx.getString("onWarrant") + " \"" + _deviceName + "\" " 975 + rbx.getString("to") + " " + getActionDataString(); 976 break; 977 default: 978 break; // nothing needed for others 979 } 980 } 981 if (_actionString.length() > 0) { 982 switch (_type) { 983 case SET_MEMORY: 984 case COPY_MEMORY: 985 str = str + " " + rbx.getString("to") + " " + _actionString + "."; 986 break; 987 case PLAY_SOUND: 988 case RUN_SCRIPT: 989 str = str + " " + rbx.getString("FromFile") + " " + _actionString + "."; 990 break; 991 case RESET_DELAYED_TURNOUT: 992 case RESET_DELAYED_SENSOR: 993 case DELAYED_TURNOUT: 994 case DELAYED_SENSOR: 995 str = str + rbx.getString("After") + " "; 996 try { 997 Float.valueOf(_actionString); 998 str = str + _actionString + " " + rbx.getString("Seconds") + "."; 999 } catch (NumberFormatException nfe) { 1000 str = str + _actionString + " " + rbx.getString("ValueInMemory") 1001 + " " + rbx.getString("Seconds") + "."; 1002 } 1003 break; 1004 case SET_LIGHT_TRANSITION_TIME: 1005 case SET_LIGHT_INTENSITY: 1006 try { 1007 //int t = Integer.parseInt(_actionString); 1008 str = str + " " + rbx.getString("to") + " " + _actionString + "."; 1009 } catch (NumberFormatException nfe) { 1010 str = str + " " + rbx.getString("to") + " " + _actionString + " " 1011 + rbx.getString("ValueInMemory") + "."; 1012 } 1013 break; 1014 case JYTHON_COMMAND: 1015 str = str + " " + rbx.getString("ExecJythonCmd") + " " + _actionString + "."; 1016 break; 1017 case SET_TRAIN_ID: 1018 case SET_TRAIN_NAME: 1019 str = str + ", \"" + _actionString + "\" " + rbx.getString("onWarrant") 1020 + " \"" + _deviceName + "\"."; 1021 break; 1022 case SET_BLOCK_VALUE: 1023 str = str + ", \"" + _actionString + "\" " + rbx.getString("onBlock") 1024 + " \"" + _deviceName + "\"."; 1025 break; 1026 default: 1027 break; // nothing needed for others 1028 } 1029 } 1030 switch (_type) { 1031 case SET_LIGHT_INTENSITY: 1032 case SET_LIGHT_TRANSITION_TIME: 1033 str = str + " " + rbx.getString("to") + " " + _actionData + "."; 1034 break; 1035 case SET_FAST_CLOCK_TIME: 1036 str = str + " " + rbx.getString("to") + " " 1037 + LogixTableAction.formatTime(_actionData / 60, _actionData - ((_actionData / 60) * 60)); 1038 break; 1039 default: 1040 break; // nothing needed for others 1041 } 1042 return str; 1043 } 1044 1045 /** {@inheritDoc} */ 1046 @Override 1047 public void dispose() { 1048 if (_sound != null) { 1049 _sound.dispose(); 1050 } 1051 } 1052 1053 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultConditionalAction.class); 1054 1055}