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