001package jmri.jmrit.logixng.actions; 002 003import java.util.*; 004 005import jmri.InstanceManager; 006import jmri.JmriException; 007import jmri.jmrit.logixng.*; 008 009/** 010 * Executes an action only one time. 011 * 012 * @author Daniel Bergqvist Copyright 2022 013 */ 014public class RunOnce extends AbstractDigitalAction 015 implements FemaleSocketListener { 016 017 private String _socketSystemName; 018 private final FemaleDigitalActionSocket _socket; 019 private boolean _hasExecuted = false; 020 021 public RunOnce(String sys, String user) { 022 super(sys, user); 023 _socket = InstanceManager.getDefault(DigitalActionManager.class) 024 .createFemaleSocket(this, this, Bundle.getMessage("RunOnce_Socket_Action")); 025 } 026 027 public RunOnce(String sys, String user, String socketName, String socketSystemName) 028 throws BadUserNameException, BadSystemNameException { 029 super(sys, user); 030 _socket = InstanceManager.getDefault(DigitalActionManager.class) 031 .createFemaleSocket(this, this, socketName); 032 _socketSystemName = socketSystemName; 033 } 034 035 @Override 036 public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws JmriException { 037 DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.class); 038 String sysName = systemNames.get(getSystemName()); 039 String userName = userNames.get(getSystemName()); 040 if (sysName == null) sysName = manager.getAutoSystemName(); 041 RunOnce copy = new RunOnce(sysName, userName); 042 copy.setComment(getComment()); 043 return manager.registerAction(copy).deepCopyChildren(this, systemNames, userNames); 044 } 045 046 /** {@inheritDoc} */ 047 @Override 048 public Category getCategory() { 049 return Category.FLOW_CONTROL; 050 } 051 052 /** {@inheritDoc} */ 053 @Override 054 public void execute() throws JmriException { 055 if (!_hasExecuted && _socket != null) { 056 _socket.execute(); 057 } 058 _hasExecuted = true; 059 } 060 061 @Override 062 public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException { 063 if (index == 0) { 064 return _socket; 065 } else { 066 throw new IllegalArgumentException(String.format("index has invalid value: %d", index)); 067 } 068 } 069 070 @Override 071 public int getChildCount() { 072 return 1; 073 } 074 075 @Override 076 public void connected(FemaleSocket socket) { 077 if (socket == this._socket) { 078 this._socketSystemName = socket.getConnectedSocket().getSystemName(); 079 } 080 } 081 082 @Override 083 public void disconnected(FemaleSocket socket) { 084 if (socket == this._socket) { 085 this._socketSystemName = null; 086 } 087 } 088 089 @Override 090 public String getShortDescription(Locale locale) { 091 return Bundle.getMessage(locale, "RunOnce_Short"); 092 } 093 094 @Override 095 public String getLongDescription(Locale locale) { 096 return Bundle.getMessage(locale, "RunOnce_Long"); 097 } 098 099 public FemaleDigitalActionSocket getSocket() { 100 return _socket; 101 } 102 103 public String getSocketSystemName() { 104 return _socketSystemName; 105 } 106 107 public void setSocketSystemName(String systemName) { 108 _socketSystemName = systemName; 109 } 110 111 /** {@inheritDoc} */ 112 @Override 113 public void setup() { 114 try { 115 if ( !_socket.isConnected() 116 || !_socket.getConnectedSocket().getSystemName() 117 .equals(_socketSystemName)) { 118 119 String socketSystemName = _socketSystemName; 120 _socket.disconnect(); 121 if (socketSystemName != null) { 122 MaleSocket maleSocket = 123 InstanceManager.getDefault(DigitalActionManager.class) 124 .getBySystemName(socketSystemName); 125 _socket.disconnect(); 126 if (maleSocket != null) { 127 _socket.connect(maleSocket); 128 maleSocket.setup(); 129 } else { 130 log.error("cannot load digital action {}", socketSystemName); 131 } 132 } 133 } else { 134 _socket.getConnectedSocket().setup(); 135 } 136 } catch (SocketAlreadyConnectedException ex) { 137 // This shouldn't happen and is a runtime error if it does. 138 throw new RuntimeException("socket is already connected"); 139 } 140 } 141 142 143 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RunOnce.class); 144 145}