001package jmri.jmrit.logixng.actions;
002
003import java.util.Locale;
004import java.util.Map;
005
006import jmri.InstanceManager;
007import jmri.JmriException;
008import jmri.jmrit.logixng.*;
009
010/**
011 * Executes an action when the expression is True.
012 *
013 * @author Daniel Bergqvist Copyright 2018
014 */
015public class For extends AbstractDigitalAction
016        implements FemaleSocketListener {
017
018    private String _initActionSocketSystemName;
019    private String _whileExpressionSocketSystemName;
020    private String _afterEachActionSocketSystemName;
021    private String _doActionSocketSystemName;
022    private final FemaleDigitalActionSocket _initActionSocket;
023    private final FemaleDigitalExpressionSocket _whileExpressionSocket;
024    private final FemaleDigitalActionSocket _afterEachActionSocket;
025    private final FemaleDigitalActionSocket _doActionSocket;
026
027    public For(String sys, String user) {
028        super(sys, user);
029        _initActionSocket = InstanceManager.getDefault(DigitalActionManager.class)
030                .createFemaleSocket(this, this, Bundle.getMessage("For_SocketName_Init"));
031        _whileExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class)
032                .createFemaleSocket(this, this, Bundle.getMessage("For_SocketName_While"));
033        _afterEachActionSocket = InstanceManager.getDefault(DigitalActionManager.class)
034                .createFemaleSocket(this, this, Bundle.getMessage("For_SocketName_AfterEach"));
035        _doActionSocket = InstanceManager.getDefault(DigitalActionManager.class)
036                .createFemaleSocket(this, this, Bundle.getMessage("For_SocketName_Do"));
037    }
038
039    @Override
040    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws JmriException {
041        DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.class);
042        String sysName = systemNames.get(getSystemName());
043        String userName = userNames.get(getSystemName());
044        if (sysName == null) sysName = manager.getAutoSystemName();
045        For copy = new For(sysName, userName);
046        copy.setComment(getComment());
047        return manager.registerAction(copy).deepCopyChildren(this, systemNames, userNames);
048    }
049
050    /** {@inheritDoc} */
051    @Override
052    public Category getCategory() {
053        return Category.FLOW_CONTROL;
054    }
055
056    /** {@inheritDoc} */
057    @Override
058    public void execute() throws JmriException {
059        _initActionSocket.execute();
060        while (_whileExpressionSocket.evaluate()) {
061            try {
062                _doActionSocket.execute();
063            } catch (BreakException e) {
064                break;
065            } catch (ContinueException e) {
066                // Do nothing, just catch it.
067            }
068            _afterEachActionSocket.execute();
069        }
070    }
071
072    @Override
073    public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException {
074        switch (index) {
075            case 0:
076                return _initActionSocket;
077
078            case 1:
079                return _whileExpressionSocket;
080
081            case 2:
082                return _afterEachActionSocket;
083
084            case 3:
085                return _doActionSocket;
086
087            default:
088                throw new IllegalArgumentException(
089                        String.format("index has invalid value: %d", index));
090        }
091    }
092
093    @Override
094    public int getChildCount() {
095        return 4;
096    }
097
098    @Override
099    public void connected(FemaleSocket socket) {
100        if (socket == _initActionSocket) {
101            _initActionSocketSystemName = socket.getConnectedSocket().getSystemName();
102        } else if (socket == _whileExpressionSocket) {
103            _whileExpressionSocketSystemName = socket.getConnectedSocket().getSystemName();
104        } else if (socket == _afterEachActionSocket) {
105            _afterEachActionSocketSystemName = socket.getConnectedSocket().getSystemName();
106        } else if (socket == _doActionSocket) {
107            _doActionSocketSystemName = socket.getConnectedSocket().getSystemName();
108        } else {
109            throw new IllegalArgumentException("unkown socket");
110        }
111    }
112
113    @Override
114    public void disconnected(FemaleSocket socket) {
115        if (socket == _initActionSocket) {
116            _initActionSocketSystemName = null;
117        } else if (socket == _whileExpressionSocket) {
118            _whileExpressionSocketSystemName = null;
119        } else if (socket == _afterEachActionSocket) {
120            _afterEachActionSocketSystemName = null;
121        } else if (socket == _doActionSocket) {
122            _doActionSocketSystemName = null;
123        } else {
124            throw new IllegalArgumentException("unkown socket");
125        }
126    }
127
128    @Override
129    public String getShortDescription(Locale locale) {
130        return Bundle.getMessage(locale, "For_Short");
131    }
132
133    @Override
134    public String getLongDescription(Locale locale) {
135        return Bundle.getMessage(locale, "For_Long",
136                _initActionSocket.getName(),
137                _whileExpressionSocket.getName(),
138                _afterEachActionSocket.getName(),
139                _doActionSocket.getName());
140    }
141
142    public FemaleDigitalActionSocket getInitActionSocket() {
143        return _initActionSocket;
144    }
145
146    public String getInitActionSocketSystemName() {
147        return _initActionSocketSystemName;
148    }
149
150    public void setInitActionSocketSystemName(String systemName) {
151        _initActionSocketSystemName = systemName;
152    }
153
154    public FemaleDigitalExpressionSocket getWhileExpressionSocket() {
155        return _whileExpressionSocket;
156    }
157
158    public String getWhileExpressionSocketSystemName() {
159        return _whileExpressionSocketSystemName;
160    }
161
162    public void setWhileExpressionSocketSystemName(String systemName) {
163        _whileExpressionSocketSystemName = systemName;
164    }
165
166    public FemaleDigitalActionSocket getAfterEachActionSocket() {
167        return _afterEachActionSocket;
168    }
169
170    public String getAfterEachExpressionSocketSystemName() {
171        return _afterEachActionSocketSystemName;
172    }
173
174    public void setAfterEachActionSocketSystemName(String systemName) {
175        _afterEachActionSocketSystemName = systemName;
176    }
177
178    public FemaleDigitalActionSocket getDoActionSocket() {
179        return _doActionSocket;
180    }
181
182    public String getDoExpressionSocketSystemName() {
183        return _doActionSocketSystemName;
184    }
185
186    public void setDoActionSocketSystemName(String systemName) {
187        _doActionSocketSystemName = systemName;
188    }
189
190    /** {@inheritDoc} */
191    @Override
192    public void setup() {
193        try {
194            if ( !_initActionSocket.isConnected()
195                    || !_initActionSocket.getConnectedSocket().getSystemName()
196                            .equals(_initActionSocketSystemName)) {
197
198                String socketSystemName = _initActionSocketSystemName;
199                _initActionSocket.disconnect();
200                if (socketSystemName != null) {
201                    MaleSocket maleSocket =
202                            InstanceManager.getDefault(DigitalActionManager.class)
203                                    .getBySystemName(socketSystemName);
204                    _initActionSocket.disconnect();
205                    if (maleSocket != null) {
206                        _initActionSocket.connect(maleSocket);
207                        maleSocket.setup();
208                    } else {
209                        log.error("cannot load digital action {}", socketSystemName);
210                    }
211                }
212            } else {
213                _initActionSocket.getConnectedSocket().setup();
214            }
215
216            if ( !_whileExpressionSocket.isConnected()
217                    || !_whileExpressionSocket.getConnectedSocket().getSystemName()
218                            .equals(_whileExpressionSocketSystemName)) {
219
220                String socketSystemName = _whileExpressionSocketSystemName;
221                _whileExpressionSocket.disconnect();
222                if (socketSystemName != null) {
223                    MaleSocket maleSocket =
224                            InstanceManager.getDefault(DigitalExpressionManager.class)
225                                    .getBySystemName(socketSystemName);
226                    if (maleSocket != null) {
227                        _whileExpressionSocket.connect(maleSocket);
228                        maleSocket.setup();
229                    } else {
230                        log.error("cannot load digital expression {}", socketSystemName);
231                    }
232                }
233            } else {
234                _whileExpressionSocket.getConnectedSocket().setup();
235            }
236
237            if ( !_afterEachActionSocket.isConnected()
238                    || !_afterEachActionSocket.getConnectedSocket().getSystemName()
239                            .equals(_afterEachActionSocketSystemName)) {
240
241                String socketSystemName = _afterEachActionSocketSystemName;
242                _afterEachActionSocket.disconnect();
243                if (socketSystemName != null) {
244                    MaleSocket maleSocket =
245                            InstanceManager.getDefault(DigitalActionManager.class)
246                                    .getBySystemName(socketSystemName);
247                    _afterEachActionSocket.disconnect();
248                    if (maleSocket != null) {
249                        _afterEachActionSocket.connect(maleSocket);
250                        maleSocket.setup();
251                    } else {
252                        log.error("cannot load digital action {}", socketSystemName);
253                    }
254                }
255            } else {
256                _afterEachActionSocket.getConnectedSocket().setup();
257            }
258
259            if ( !_doActionSocket.isConnected()
260                    || !_doActionSocket.getConnectedSocket().getSystemName()
261                            .equals(_doActionSocketSystemName)) {
262
263                String socketSystemName = _doActionSocketSystemName;
264                _doActionSocket.disconnect();
265                if (socketSystemName != null) {
266                    MaleSocket maleSocket =
267                            InstanceManager.getDefault(DigitalActionManager.class)
268                                    .getBySystemName(socketSystemName);
269                    _doActionSocket.disconnect();
270                    if (maleSocket != null) {
271                        _doActionSocket.connect(maleSocket);
272                        maleSocket.setup();
273                    } else {
274                        log.error("cannot load digital action {}", socketSystemName);
275                    }
276                }
277            } else {
278                _doActionSocket.getConnectedSocket().setup();
279            }
280        } catch (SocketAlreadyConnectedException ex) {
281            // This shouldn't happen and is a runtime error if it does.
282            throw new RuntimeException("socket is already connected");
283        }
284    }
285
286    /** {@inheritDoc} */
287    @Override
288    public void registerListenersForThisClass() {
289    }
290
291    /** {@inheritDoc} */
292    @Override
293    public void unregisterListenersForThisClass() {
294    }
295
296    /** {@inheritDoc} */
297    @Override
298    public void disposeMe() {
299    }
300
301    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(For.class);
302
303}