001package jmri.jmrit.logixng.implementation; 002 003import java.beans.*; 004import java.io.PrintWriter; 005import java.util.*; 006 007import javax.annotation.Nonnull; 008 009import jmri.*; 010import jmri.jmrit.logixng.*; 011import jmri.jmrit.logixng.Module; 012import jmri.jmrit.logixng.SymbolTable.VariableData; 013import jmri.jmrit.logixng.actions.*; 014import jmri.jmrit.logixng.implementation.swing.ErrorHandlingDialog; 015import jmri.jmrit.logixng.implementation.swing.ErrorHandlingDialog_MultiLine; 016import jmri.jmrit.logixng.util.LogixNG_Thread; 017import jmri.util.LoggingUtil; 018import jmri.util.ThreadingUtil; 019 020import org.apache.commons.lang3.mutable.MutableInt; 021import org.slf4j.Logger; 022 023/** 024 * The abstract class that is the base class for all LogixNG classes that 025 * implements the Base interface. 026 * 027 * @author Daniel Bergqvist 2020 028 */ 029public abstract class AbstractMaleSocket implements MaleSocket { 030 031 private final Base _object; 032 private boolean _locked = false; 033 private boolean _system = false; 034 protected final List<VariableData> _localVariables = new ArrayList<>(); 035 private final BaseManager<? extends NamedBean> _manager; 036 private Base _parent; 037 private ErrorHandlingType _errorHandlingType = ErrorHandlingType.Default; 038 private boolean _catchAbortExecution; 039 private boolean _listen = true; // By default, actions and expressions listen 040 041 042 private static class ErrorHandlingModuleClass { 043 044 private static final ErrorHandlingModuleClass INSTANCE = new ErrorHandlingModuleClass(); 045 046 private final LogixNG errorHandlingLogixNG; 047 private final ConditionalNG errorHandlingConditionalNG; 048 private final Module errorHandlingModule; 049 private final Map<String, Object> _variablesWithValues; 050 051 private ErrorHandlingModuleClass() { 052 errorHandlingLogixNG = new DefaultLogixNG("IQ:JMRI:ErrorHandlingLogixNG", null); 053 errorHandlingConditionalNG = new DefaultConditionalNG("IQC:JMRI:ErrorHandlingCondtionalNG", null, LogixNG_Thread.ERROR_HANDLING_LOGIXNG_THREAD); 054 errorHandlingLogixNG.addConditionalNG(errorHandlingConditionalNG); 055 056 Module tempErrorHandlingModule = InstanceManager.getDefault(ModuleManager.class).getBySystemName(LogixNG_Manager.ERROR_HANDLING_MODULE_NAME); 057 if (tempErrorHandlingModule != null) { 058 errorHandlingModule = tempErrorHandlingModule; 059 } else { 060 FemaleSocketManager.SocketType socketType = InstanceManager.getDefault( 061 FemaleSocketManager.class).getSocketTypeByType("DefaultFemaleDigitalActionSocket"); 062 errorHandlingModule = new DefaultModule(LogixNG_Manager.ERROR_HANDLING_MODULE_NAME, null, socketType, false, false); 063 InstanceManager.getDefault(ModuleManager.class).register(errorHandlingModule); 064 } 065 066 067 DigitalMany many = new DigitalMany("IQDA:JMRI:ErrorHandlingAction", null); 068 MaleSocket maleSocketMany = new DefaultMaleDigitalActionSocket( 069 InstanceManager.getDefault(DigitalActionManager.class), many); 070 many.setParent(maleSocketMany); 071 072 maleSocketMany.addLocalVariable("logixng", SymbolTable.InitialValueType.String, null); 073 maleSocketMany.addLocalVariable("conditionalng", SymbolTable.InitialValueType.String, null); 074 maleSocketMany.addLocalVariable("module", SymbolTable.InitialValueType.String, null); 075 maleSocketMany.addLocalVariable("item", SymbolTable.InitialValueType.String, null); 076 maleSocketMany.addLocalVariable("message", SymbolTable.InitialValueType.String, null); 077 maleSocketMany.addLocalVariable("messageList", SymbolTable.InitialValueType.String, null); 078 maleSocketMany.addLocalVariable("exception", SymbolTable.InitialValueType.String, null); 079 080 try { 081 errorHandlingConditionalNG.getFemaleSocket().connect(maleSocketMany); 082 } catch (SocketAlreadyConnectedException e) { 083 log.error("Exception when creating error handling LogixNG: ", e); 084 } 085 086 SetLocalVariables setLocalVariables = new SetLocalVariables("IQDA:JMRI:ErrorHandlingAction", null); 087 MaleSocket maleSocketSetLocalVariables = new DefaultMaleDigitalActionSocket( 088 InstanceManager.getDefault(DigitalActionManager.class), setLocalVariables); 089 setLocalVariables.setParent(maleSocketSetLocalVariables); 090 _variablesWithValues = setLocalVariables.getMap(); 091 092 try { 093 maleSocketMany.getChild(maleSocketMany.getChildCount()-1).connect(maleSocketSetLocalVariables); 094 } catch (SocketAlreadyConnectedException e) { 095 log.error("Exception when creating error handling LogixNG: ", e); 096 } 097 098 DigitalCallModule action = new DigitalCallModule("IQDA:JMRI:ErrorHandlingAction", null); 099 action.getSelectNamedBean().setNamedBean(errorHandlingModule); 100 action.addParameter("__logixng__", SymbolTable.InitialValueType.LocalVariable, "logixng", Module.ReturnValueType.None, null); 101 action.addParameter("__conditionalng__", SymbolTable.InitialValueType.LocalVariable, "conditionalng", Module.ReturnValueType.None, null); 102 action.addParameter("__module__", SymbolTable.InitialValueType.LocalVariable, "module", Module.ReturnValueType.None, null); 103 action.addParameter("__item__", SymbolTable.InitialValueType.LocalVariable, "item", Module.ReturnValueType.None, null); 104 action.addParameter("__message__", SymbolTable.InitialValueType.LocalVariable, "message", Module.ReturnValueType.None, null); 105 action.addParameter("__messageList__", SymbolTable.InitialValueType.LocalVariable, "messageList", Module.ReturnValueType.None, null); 106 action.addParameter("__exception__", SymbolTable.InitialValueType.LocalVariable, "exception", Module.ReturnValueType.None, null); 107 MaleSocket maleSocket = new DefaultMaleDigitalActionSocket(InstanceManager.getDefault(DigitalActionManager.class), action); 108 action.setParent(maleSocket); 109 try { 110 maleSocketMany.getChild(maleSocketMany.getChildCount()-1).connect(maleSocket); 111 } catch (SocketAlreadyConnectedException e) { 112 log.error("Exception when creating error handling LogixNG: ", e); 113 } 114 List<String> errors = new ArrayList<>(); 115 errorHandlingLogixNG.setParentForAllChildren(errors); 116 if (!errors.isEmpty()) { 117 for (String s : errors) { 118 log.error("Error: {}", s); 119 } 120 } 121 } 122 } 123 124 125 public AbstractMaleSocket(BaseManager<? extends NamedBean> manager, Base object) { 126 _manager = manager; 127 _object = object; 128 } 129 130 public static FemaleSocket getErrorHandlingModuleSocket() { 131 return ErrorHandlingModuleClass.INSTANCE.errorHandlingModule.getRootSocket(); 132 } 133 134 public static boolean isErrorHandlingModuleEnabled() { 135 // Does the error handling module exist? 136 Module errorHandlingModule = InstanceManager.getDefault(ModuleManager.class) 137 .getBySystemName(LogixNG_Manager.ERROR_HANDLING_MODULE_NAME); 138 if (errorHandlingModule == null) { 139 return false; 140 } 141 return errorHandlingModule.getRootSocket().isConnected(); 142 } 143 144 /** {@inheritDoc} */ 145 @Override 146 public final Base getObject() { 147 return _object; 148 } 149 150 /** {@inheritDoc} */ 151 @Override 152 public final Base getRoot() { 153 return _object.getRoot(); 154 } 155 156 /** {@inheritDoc} */ 157 @Override 158 public boolean isLocked() { 159 if (_object instanceof MaleSocket) { 160 return ((MaleSocket)_object).isLocked(); 161 } 162 return _locked; 163 } 164 165 /** {@inheritDoc} */ 166 @Override 167 public void setLocked(boolean locked) { 168 if (_object instanceof MaleSocket) { 169 ((MaleSocket)_object).setLocked(locked); 170 } 171 _locked = locked; 172 } 173 174 /** {@inheritDoc} */ 175 @Override 176 public boolean isSystem() { 177 if (_object instanceof MaleSocket) { 178 return ((MaleSocket)_object).isSystem(); 179 } 180 return _system; 181 } 182 183 /** {@inheritDoc} */ 184 @Override 185 public void setSystem(boolean system) { 186 if (_object instanceof MaleSocket) { 187 ((MaleSocket)_object).setSystem(system); 188 } 189 _system = system; 190 } 191 192 /** {@inheritDoc} */ 193 @Override 194 public final Category getCategory() { 195 return _object.getCategory(); 196 } 197 198 @Override 199 public final FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException { 200 return _object.getChild(index); 201 } 202 203 @Override 204 public final int getChildCount() { 205 return _object.getChildCount(); 206 } 207 208 @Override 209 public final String getShortDescription(Locale locale) { 210 return _object.getShortDescription(locale); 211 } 212 213 @Override 214 public final String getLongDescription(Locale locale) { 215 String s = _object.getLongDescription(locale); 216 if (!_listen) { 217 s += " ::: " + Base.getNoListenString(); 218 } 219 return s; 220 } 221 222 @Override 223 public final String getUserName() { 224 return _object.getUserName(); 225 } 226 227 @Override 228 public final void setUserName(String s) throws NamedBean.BadUserNameException { 229 _object.setUserName(s); 230 } 231 232 @Override 233 public final String getSystemName() { 234 return _object.getSystemName(); 235 } 236 237 @Override 238 public final void addPropertyChangeListener(PropertyChangeListener l, String name, String listenerRef) { 239 _object.addPropertyChangeListener(l, name, listenerRef); 240 } 241 242 @Override 243 public final void addPropertyChangeListener(String propertyName, PropertyChangeListener l, String name, String listenerRef) { 244 _object.addPropertyChangeListener(propertyName, l, name, listenerRef); 245 } 246 247 @Override 248 public final void addPropertyChangeListener(PropertyChangeListener l) { 249 _object.addPropertyChangeListener(l); 250 } 251 252 @Override 253 public final void addPropertyChangeListener(String propertyName, PropertyChangeListener l) { 254 _object.addPropertyChangeListener(propertyName, l); 255 } 256 257 @Override 258 public final void removePropertyChangeListener(PropertyChangeListener l) { 259 _object.removePropertyChangeListener(l); 260 } 261 262 @Override 263 public final void removePropertyChangeListener(String propertyName, PropertyChangeListener l) { 264 _object.removePropertyChangeListener(propertyName, l); 265 } 266 267 @Override 268 public final void updateListenerRef(PropertyChangeListener l, String newName) { 269 _object.updateListenerRef(l, newName); 270 } 271 272 @Override 273 public final void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { 274 _object.vetoableChange(evt); 275 } 276 277 @Override 278 public final String getListenerRef(PropertyChangeListener l) { 279 return _object.getListenerRef(l); 280 } 281 282 @Override 283 public final ArrayList<String> getListenerRefs() { 284 return _object.getListenerRefs(); 285 } 286 287 @Override 288 public final int getNumPropertyChangeListeners() { 289 return _object.getNumPropertyChangeListeners(); 290 } 291 292 @Override 293 public final synchronized PropertyChangeListener[] getPropertyChangeListeners() { 294 return _object.getPropertyChangeListeners(); 295 } 296 297 @Override 298 public final synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { 299 return _object.getPropertyChangeListeners(propertyName); 300 } 301 302 @Override 303 public final PropertyChangeListener[] getPropertyChangeListenersByReference(String name) { 304 return _object.getPropertyChangeListenersByReference(name); 305 } 306 307 @Override 308 public String getComment() { 309 return _object.getComment(); 310 } 311 312 @Override 313 public void setComment(String comment) { 314 _object.setComment(comment); 315 } 316 317 @Override 318 public boolean getListen() { 319 if (getObject() instanceof MaleSocket) { 320 return ((MaleSocket)getObject()).getListen(); 321 } 322 return _listen; 323 } 324 325 @Override 326 public void setListen(boolean listen) 327 { 328 if (getObject() instanceof MaleSocket) { 329 ((MaleSocket)getObject()).setListen(listen); 330 } 331 _listen = listen; 332 } 333 334 @Override 335 public boolean getCatchAbortExecution() { 336 return _catchAbortExecution; 337 } 338 339 @Override 340 public void setCatchAbortExecution(boolean catchAbortExecution) 341 { 342 _catchAbortExecution = catchAbortExecution; 343 } 344 345 @Override 346 public void addLocalVariable( 347 String name, 348 SymbolTable.InitialValueType initialValueType, 349 String initialValueData) { 350 351 if (getObject() instanceof MaleSocket) { 352 ((MaleSocket)getObject()).addLocalVariable(name, initialValueType, initialValueData); 353 } else { 354 _localVariables.add(new VariableData(name, initialValueType, initialValueData)); 355 } 356 } 357 358 @Override 359 public void addLocalVariable(VariableData variableData) { 360 361 if (getObject() instanceof MaleSocket) { 362 ((MaleSocket)getObject()).addLocalVariable(variableData); 363 } else { 364 _localVariables.add(variableData); 365 } 366 } 367 368 @Override 369 public void clearLocalVariables() { 370 if (getObject() instanceof MaleSocket) { 371 ((MaleSocket)getObject()).clearLocalVariables(); 372 } else { 373 _localVariables.clear(); 374 } 375 } 376 377 @Override 378 public List<VariableData> getLocalVariables() { 379 if (getObject() instanceof MaleSocket) { 380 return ((MaleSocket)getObject()).getLocalVariables(); 381 } else { 382 return _localVariables; 383 } 384 } 385 386 @Override 387 public Base getParent() { 388 return _parent; 389 } 390 391 @Override 392 public void setParent(Base parent) { 393 _parent = parent; 394 } 395 396 @Override 397 public final ConditionalNG getConditionalNG() { 398 if (getParent() == null) return null; 399 return getParent().getConditionalNG(); 400 } 401 402 @Override 403 public final LogixNG getLogixNG() { 404 if (getParent() == null) return null; 405 return getParent().getLogixNG(); 406 } 407 408 /** {@inheritDoc} */ 409 @Override 410 public final boolean setParentForAllChildren(List<String> errors) { 411 boolean result = true; 412 for (int i=0; i < getChildCount(); i++) { 413 FemaleSocket femaleSocket = getChild(i); 414 if (femaleSocket.isConnected()) { 415 MaleSocket connectedSocket = femaleSocket.getConnectedSocket(); 416 connectedSocket.setParent(femaleSocket); 417 result = result && connectedSocket.setParentForAllChildren(errors); 418 } 419 } 420 return result; 421 } 422 423 /** 424 * Register listeners if this object needs that. 425 * <P> 426 * Important: This method may be called more than once. Methods overriding 427 * this method must ensure that listeners are not registered more than once. 428 */ 429 abstract protected void registerListenersForThisClass(); 430 431 /** 432 * Unregister listeners if this object needs that. 433 * <P> 434 * Important: This method may be called more than once. Methods overriding 435 * this method must ensure that listeners are not unregistered more than once. 436 */ 437 abstract protected void unregisterListenersForThisClass(); 438 439 /** {@inheritDoc} */ 440 @Override 441 public final void registerListeners() { 442 if (getObject() instanceof MaleSocket) { 443 getObject().registerListeners(); 444 } else { 445 if (_listen) { 446 registerListenersForThisClass(); 447 for (int i=0; i < getChildCount(); i++) { 448 getChild(i).registerListeners(); 449 } 450 } 451 } 452 } 453 454 /** {@inheritDoc} */ 455 @Override 456 public final void unregisterListeners() { 457 if (getObject() instanceof MaleSocket) { 458 getObject().unregisterListeners(); 459 } else { 460 unregisterListenersForThisClass(); 461 for (int i=0; i < getChildCount(); i++) { 462 getChild(i).unregisterListeners(); 463 } 464 } 465 } 466 467 /** {@inheritDoc} */ 468 @Override 469 public final boolean isActive() { 470 return isEnabled() && ((getParent() == null) || getParent().isActive()); 471 } 472 473 /** 474 * Print this row. 475 * If getObject() doesn't return an AbstractMaleSocket, print this row. 476 * <P> 477 * If a male socket that extends AbstractMaleSocket wants to print 478 * something here, it needs to override this method. 479 * <P> 480 * The reason this method doesn't print if getObject() returns an 481 * AbstractMaleSocket is to protect so it doesn't print itself twice if 482 * it's embedding an other AbstractMaleSocket. An example of this is the 483 * AbstractDebuggerMaleSocket which embeds other male sockets. 484 * 485 * @param settings settings for what to print 486 * @param locale The locale to be used 487 * @param writer the stream to print the tree to 488 * @param currentIndent the current indentation 489 * @param lineNumber the line number 490 */ 491 protected void printTreeRow( 492 PrintTreeSettings settings, 493 Locale locale, 494 PrintWriter writer, 495 String currentIndent, 496 MutableInt lineNumber) { 497 498 if (!(getObject() instanceof AbstractMaleSocket)) { 499 String comment = getComment(); 500 if (comment != null) { 501 comment = comment.replaceAll("\\r\\n", "\\n"); 502 comment = comment.replaceAll("\\r", "\\n"); 503 for (String s : comment.split("\\n", 0)) { 504 if (settings._printLineNumbers) { 505 writer.append(String.format(PRINT_LINE_NUMBERS_FORMAT, lineNumber.addAndGet(1))); 506 } 507 writer.append(currentIndent); 508 writer.append("// "); 509 writer.append(s); 510 writer.println(); 511 } 512 } 513 if (settings._printLineNumbers) { 514 writer.append(String.format(PRINT_LINE_NUMBERS_FORMAT, lineNumber.addAndGet(1))); 515 } 516 writer.append(currentIndent); 517 writer.append(getLongDescription(locale)); 518 if (settings._printSystemNames) { 519 writer.append(" ::: "); 520 writer.append(this.getSystemName()); 521 } 522 if (settings._printDisplayName) { 523 writer.append(" ::: "); 524 writer.append(Bundle.getMessage("LabelDisplayName")); 525 writer.append(" "); 526 writer.append(((NamedBean)this).getDisplayName( 527 NamedBean.DisplayOptions.USERNAME_SYSTEMNAME)); 528 } else if (!settings._hideUserName && getUserName() != null) { 529 writer.append(" ::: "); 530 writer.append(Bundle.getMessage("LabelUserName")); 531 writer.append(" "); 532 writer.append(getUserName()); 533 } 534 535 if (settings._printErrorHandling) { 536 writer.append(" ::: "); 537 writer.append(getErrorHandlingType().toString()); 538 } 539 if (!isEnabled()) { 540 writer.append(" ::: "); 541 writer.append(Bundle.getMessage("AbstractMaleSocket_Disabled")); 542 } 543 if (isLocked()) { 544 writer.append(" ::: "); 545 writer.append(Bundle.getMessage("AbstractMaleSocket_Locked")); 546 } 547 if (isSystem()) { 548 writer.append(" ::: "); 549 writer.append(Bundle.getMessage("AbstractMaleSocket_System")); 550 } 551 writer.println(); 552 } 553 } 554 555 protected void printLocalVariable( 556 PrintTreeSettings settings, 557 Locale locale, 558 PrintWriter writer, 559 String currentIndent, 560 MutableInt lineNumber, 561 VariableData localVariable) { 562 563 if (settings._printLineNumbers) { 564 writer.append(String.format(PRINT_LINE_NUMBERS_FORMAT, lineNumber.addAndGet(1))); 565 } 566 writer.append(currentIndent); 567 writer.append(" ::: "); 568 writer.append(Bundle.getMessage( 569 locale, 570 "PrintLocalVariable", 571 localVariable._name, 572 localVariable._initialValueType.toString(), 573 localVariable._initialValueData)); 574 writer.println(); 575 } 576 577 /** {@inheritDoc} */ 578 @Override 579 public void printTree( 580 PrintTreeSettings settings, 581 PrintWriter writer, 582 String indent, 583 MutableInt lineNumber) { 584 printTree(settings, Locale.getDefault(), writer, indent, "", lineNumber); 585 } 586 587 /** {@inheritDoc} */ 588 @Override 589 public void printTree( 590 PrintTreeSettings settings, 591 Locale locale, 592 PrintWriter writer, 593 String indent, 594 MutableInt lineNumber) { 595 printTree(settings, locale, writer, indent, "", lineNumber); 596 } 597 598 /** {@inheritDoc} */ 599 @Override 600 public void printTree( 601 PrintTreeSettings settings, 602 Locale locale, 603 PrintWriter writer, 604 String indent, 605 String currentIndent, 606 MutableInt lineNumber) { 607 608 printTreeRow(settings, locale, writer, currentIndent, lineNumber); 609 610 if (settings._printLocalVariables) { 611 for (VariableData localVariable : _localVariables) { 612 printLocalVariable(settings, locale, writer, currentIndent, lineNumber, localVariable); 613 } 614 } 615 616 if (getObject() instanceof MaleSocket) { 617 getObject().printTree(settings, locale, writer, indent, currentIndent, lineNumber); 618 } else { 619 for (int i=0; i < getChildCount(); i++) { 620 getChild(i).printTree(settings, locale, writer, indent, currentIndent+indent, lineNumber); 621 } 622 } 623 } 624 625 /** {@inheritDoc} */ 626 @Override 627 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value="SLF4J_SIGN_ONLY_FORMAT", 628 justification="Specific log message format") 629 public void getUsageTree(int level, NamedBean bean, List<NamedBeanUsageReport> report, NamedBean cdl) { 630 if (!(getObject() instanceof AbstractMaleSocket)) { 631 log.debug("*@ {} :: {}", level, this.getLongDescription()); 632 _object.getUsageDetail(level, bean, report, cdl); 633 } 634 635 if (getObject() instanceof MaleSocket) { 636 getObject().getUsageTree(level, bean, report, cdl); 637 } else { 638 level++; 639 for (int i=0; i < getChildCount(); i++) { 640 getChild(i).getUsageTree(level, bean, report, cdl); 641 } 642 } 643 } 644 645 /** {@inheritDoc} */ 646 @Override 647 public void getUsageDetail(int level, NamedBean bean, List<jmri.NamedBeanUsageReport> report, NamedBean cdl) { 648 } 649 650 @Override 651 public BaseManager<? extends NamedBean> getManager() { 652 return _manager; 653 } 654 655 @Override 656 public final Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) 657 throws JmriException { 658 659 MaleSocket maleSocket = (MaleSocket)getObject().getDeepCopy(systemNames, userNames); 660 661 maleSocket.setComment(this.getComment()); 662 if (maleSocket.getDebugConfig() != null) { 663 maleSocket.setDebugConfig(maleSocket.getDebugConfig().getCopy()); 664 } 665 maleSocket.setEnabledFlag(isEnabled()); 666 maleSocket.setListen(getListen()); 667 maleSocket.setErrorHandlingType(getErrorHandlingType()); 668 maleSocket.setLocked(isLocked()); 669 maleSocket.setSystem(false); // If a system item is copied, the new item is not treated as system 670 maleSocket.setCatchAbortExecution(getCatchAbortExecution()); 671 672 for (VariableData data : _localVariables) { 673 maleSocket.addLocalVariable(data._name, data._initialValueType, data._initialValueData); 674 } 675 676 return maleSocket; 677 } 678 679 @Override 680 public final Base deepCopyChildren(Base original, Map<String, String> systemNames, Map<String, String> userNames) throws JmriException { 681 getObject().deepCopyChildren(original, systemNames, userNames); 682 return this; 683 } 684 685 /** 686 * Disposes this object. 687 * This must remove _all_ connections! 688 */ 689 abstract protected void disposeMe(); 690 691 /** {@inheritDoc} */ 692 @Override 693 public final void dispose() { 694 for (int i=0; i < getChildCount(); i++) { 695 getChild(i).dispose(); 696 } 697 disposeMe(); 698 } 699 700 @Override 701 public ErrorHandlingType getErrorHandlingType() { 702 if (getObject() instanceof MaleSocket) { 703 return ((MaleSocket)getObject()).getErrorHandlingType(); 704 } else { 705 return _errorHandlingType; 706 } 707 } 708 709 @Override 710 public void setErrorHandlingType(ErrorHandlingType errorHandlingType) 711 { 712 if (getObject() instanceof MaleSocket) { 713 ((MaleSocket)getObject()).setErrorHandlingType(errorHandlingType); 714 } else { 715 _errorHandlingType = errorHandlingType; 716 } 717 } 718 719 /** 720 * Executes the error handling module. 721 * @param item the item that had the error 722 * @param message the error message 723 * @param messageList a list of error messages 724 * @param e the exception that has happened 725 */ 726 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings({"SLF4J_SIGN_ONLY_FORMAT"}) 727 // justification="The message is on several lines") 728 public void executeErrorHandlingModule( 729 Base item, 730 String message, 731 List<String> messageList, 732 Exception e) { 733 734 // Don't call the error handling module if it doesnt exist. 735 Module errorHandlingModule = InstanceManager.getDefault(ModuleManager.class) 736 .getBySystemName(LogixNG_Manager.ERROR_HANDLING_MODULE_NAME); 737 if (errorHandlingModule == null) { 738 return; 739 } 740 741 // Don't call the error handling module if it hasn't any children. 742 if (!ErrorHandlingModuleClass.INSTANCE.errorHandlingModule.getRootSocket().isConnected()) { 743 return; 744 } 745 746 // Don't call the error handling module recursively. It would happen 747 // if there is an error in the error handling module. 748 if (item.getModule() == ErrorHandlingModuleClass.INSTANCE.errorHandlingModule) { 749 log.warn("Exception in LogixNG error handling module. Can't execute error handling module recursively."); 750 if (messageList != null) { 751 for (String s : messageList) { 752 log.warn(" {}", s); 753 } 754 } else { 755 log.warn(" {}", message); 756 } 757 log.warn("Exception: ", e); 758 } 759 760 ErrorHandlingModuleClass.INSTANCE._variablesWithValues.put("logixng", item.getLogixNG()); 761 ErrorHandlingModuleClass.INSTANCE._variablesWithValues.put("conditionalng", item.getConditionalNG()); 762 ErrorHandlingModuleClass.INSTANCE._variablesWithValues.put("module", item.getModule()); 763 ErrorHandlingModuleClass.INSTANCE._variablesWithValues.put("item", item); 764 ErrorHandlingModuleClass.INSTANCE._variablesWithValues.put("message", message); 765 ErrorHandlingModuleClass.INSTANCE._variablesWithValues.put("messageList", messageList); 766 ErrorHandlingModuleClass.INSTANCE._variablesWithValues.put("exception", e); 767 ErrorHandlingModuleClass.INSTANCE.errorHandlingConditionalNG.execute(); 768 } 769 770 @Override 771 public void handleError(Base item, String message, JmriException e, Logger log) throws JmriException { 772 773 // Always throw AbortConditionalNGExecutionException exceptions 774 if (!_catchAbortExecution && (e instanceof AbortConditionalNGExecutionException)) throw e; 775 776 ErrorHandlingType errorHandlingType = getErrorHandlingType(); 777 if (errorHandlingType == ErrorHandlingType.Default) { 778 errorHandlingType = InstanceManager.getDefault(LogixNGPreferences.class) 779 .getErrorHandlingType(); 780 } 781 782 executeErrorHandlingModule(item, message, null, e); 783 784 switch (errorHandlingType) { 785 case ShowDialogBox: 786 boolean abort = ThreadingUtil.runOnGUIwithReturn(() -> { 787 ErrorHandlingDialog dialog = new ErrorHandlingDialog(); 788 return dialog.showDialog(item, message); 789 }); 790 if (abort) throw new AbortConditionalNGExecutionException(this, e); 791 break; 792 793 case LogError: 794 log.error("item {}, {} thrown an exception: {}", item.toString(), getObject().toString(), e, e); 795 break; 796 797 case LogErrorOnce: 798 LoggingUtil.warnOnce(log, "item {}, {} thrown an exception: {}", item.toString(), getObject().toString(), e, e); 799 break; 800 801 case ThrowException: 802 throw e; 803 804 case AbortExecution: 805 log.error("item {}, {} thrown an exception: {}", item.toString(), getObject().toString(), e, e); 806 throw new AbortConditionalNGExecutionException(this, e); 807 808 case AbortWithoutError: 809 throw new AbortConditionalNG_IgnoreException(this, e); 810 811 default: 812 throw e; 813 } 814 } 815 816 @Override 817 public void handleError( 818 Base item, 819 String message, 820 List<String> messageList, 821 JmriException e, 822 Logger log) 823 throws JmriException { 824 825 ErrorHandlingType errorHandlingType = getErrorHandlingType(); 826 if (errorHandlingType == ErrorHandlingType.Default) { 827 errorHandlingType = InstanceManager.getDefault(LogixNGPreferences.class) 828 .getErrorHandlingType(); 829 } 830 831 executeErrorHandlingModule(item, message, messageList, e); 832 833 switch (errorHandlingType) { 834 case ShowDialogBox: 835 boolean abort = ThreadingUtil.runOnGUIwithReturn(() -> { 836 ErrorHandlingDialog_MultiLine dialog = new ErrorHandlingDialog_MultiLine(); 837 return dialog.showDialog(item, message, messageList); 838 }); 839 if (abort) throw new AbortConditionalNGExecutionException(this, e); 840 break; 841 842 case LogError: 843 log.error("item {}, {} thrown an exception: {}", item.toString(), getObject().toString(), e, e); 844 break; 845 846 case LogErrorOnce: 847 LoggingUtil.warnOnce(log, "item {}, {} thrown an exception: {}", item.toString(), getObject().toString(), e, e); 848 break; 849 850 case ThrowException: 851 throw e; 852 853 case AbortExecution: 854 log.error("item {}, {} thrown an exception: {}", item.toString(), getObject().toString(), e, e); 855 throw new AbortConditionalNGExecutionException(this, e); 856 857 case AbortWithoutError: 858 throw new AbortConditionalNG_IgnoreException(this, e); 859 860 default: 861 throw e; 862 } 863 } 864 865 @Override 866 public void handleError(Base item, String message, RuntimeException e, Logger log) throws JmriException { 867 868 ErrorHandlingType errorHandlingType = getErrorHandlingType(); 869 if (errorHandlingType == ErrorHandlingType.Default) { 870 errorHandlingType = InstanceManager.getDefault(LogixNGPreferences.class) 871 .getErrorHandlingType(); 872 } 873 874 executeErrorHandlingModule(item, message, null, e); 875 876 switch (errorHandlingType) { 877 case ShowDialogBox: 878 boolean abort = ThreadingUtil.runOnGUIwithReturn(() -> { 879 ErrorHandlingDialog dialog = new ErrorHandlingDialog(); 880 return dialog.showDialog(item, message); 881 }); 882 if (abort) throw new AbortConditionalNGExecutionException(this, e); 883 break; 884 885 case LogError: 886// e.printStackTrace(); 887 log.error("item {}, {} thrown an exception: {}", item.toString(), getObject().toString(), e, e); 888 break; 889 890 case LogErrorOnce: 891// e.printStackTrace(); 892 LoggingUtil.warnOnce(log, "item {}, {} thrown an exception: {}", item.toString(), getObject().toString(), e, e); 893 break; 894 895 case ThrowException: 896 throw e; 897 898 case AbortExecution: 899 throw new AbortConditionalNGExecutionException(this, e); 900 901 case AbortWithoutError: 902 throw new AbortConditionalNG_IgnoreException(this, e); 903 904 default: 905 throw e; 906 } 907 } 908 909 /** {@inheritDoc} */ 910 @Override 911 public void getListenerRefsIncludingChildren(List<String> list) { 912 list.addAll(getListenerRefs()); 913 for (int i=0; i < getChildCount(); i++) { 914 getChild(i).getListenerRefsIncludingChildren(list); 915 } 916 } 917 918 @Override 919 public boolean hasChild(@Nonnull Base b) { 920 return getObject() == b; 921 } 922 923 /** {@inheritDoc} */ 924 @Override 925 public String toString() { 926 return getObject().toString(); 927 } 928 929 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractMaleSocket.class); 930}