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.AnalogActionManager;
009import jmri.jmrit.logixng.AnalogExpressionManager;
010import jmri.jmrit.logixng.Base;
011import jmri.jmrit.logixng.Category;
012import jmri.jmrit.logixng.DigitalActionManager;
013import jmri.jmrit.logixng.FemaleAnalogActionSocket;
014import jmri.jmrit.logixng.FemaleAnalogExpressionSocket;
015import jmri.jmrit.logixng.FemaleSocket;
016import jmri.jmrit.logixng.FemaleSocketListener;
017import jmri.jmrit.logixng.MaleSocket;
018import jmri.jmrit.logixng.SocketAlreadyConnectedException;
019
020/**
021 * Executes an analog action with the result of an analog expression.
022 * 
023 * @author Daniel Bergqvist Copyright 2018
024 */
025public class DoAnalogAction
026        extends AbstractDigitalAction
027        implements FemaleSocketListener {
028
029    private String _analogExpressionSocketSystemName;
030    private String _analogActionSocketSystemName;
031    private final FemaleAnalogExpressionSocket _analogExpressionSocket;
032    private final FemaleAnalogActionSocket _analogActionSocket;
033    
034    public DoAnalogAction(String sys, String user) {
035        super(sys, user);
036        _analogExpressionSocket = InstanceManager.getDefault(AnalogExpressionManager.class)
037                .createFemaleSocket(this, this, "E");
038        _analogActionSocket = InstanceManager.getDefault(AnalogActionManager.class)
039                .createFemaleSocket(this, this, "A");
040    }
041    
042    @Override
043    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws JmriException {
044        DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.class);
045        String sysName = systemNames.get(getSystemName());
046        String userName = userNames.get(getSystemName());
047        if (sysName == null) sysName = manager.getAutoSystemName();
048        DoAnalogAction copy = new DoAnalogAction(sysName, userName);
049        copy.setComment(getComment());
050        return manager.registerAction(copy).deepCopyChildren(this, systemNames, userNames);
051    }
052    
053    /** {@inheritDoc} */
054    @Override
055    public Category getCategory() {
056        return Category.COMMON;
057    }
058
059    /** {@inheritDoc} */
060    @Override
061    public void execute() throws JmriException {
062        double result = _analogExpressionSocket.evaluate();
063        
064        _analogActionSocket.setValue(result);
065    }
066
067    @Override
068    public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException {
069        switch (index) {
070            case 0:
071                return _analogExpressionSocket;
072                
073            case 1:
074                return _analogActionSocket;
075                
076            default:
077                throw new IllegalArgumentException(
078                        String.format("index has invalid value: %d", index));
079        }
080    }
081
082    @Override
083    public int getChildCount() {
084        return 2;
085    }
086
087    @Override
088    public void connected(FemaleSocket socket) {
089        if (socket == _analogExpressionSocket) {
090            _analogExpressionSocketSystemName = socket.getConnectedSocket().getSystemName();
091        } else if (socket == _analogActionSocket) {
092            _analogActionSocketSystemName = socket.getConnectedSocket().getSystemName();
093        } else {
094            throw new IllegalArgumentException("unkown socket");
095        }
096    }
097
098    @Override
099    public void disconnected(FemaleSocket socket) {
100        if (socket == _analogExpressionSocket) {
101            _analogExpressionSocketSystemName = null;
102        } else if (socket == _analogActionSocket) {
103            _analogActionSocketSystemName = null;
104        } else {
105            throw new IllegalArgumentException("unkown socket");
106        }
107    }
108
109    @Override
110    public String getShortDescription(Locale locale) {
111        return Bundle.getMessage(locale, "DoAnalogAction_Short");
112    }
113
114    @Override
115    public String getLongDescription(Locale locale) {
116        return Bundle.getMessage(locale, "DoAnalogAction_Long", _analogExpressionSocket.getName(), _analogActionSocket.getName());
117    }
118
119    public FemaleAnalogActionSocket getAnalogActionSocket() {
120        return _analogActionSocket;
121    }
122
123    public String getAnalogActionSocketSystemName() {
124        return _analogActionSocketSystemName;
125    }
126
127    public void setAnalogActionSocketSystemName(String systemName) {
128        _analogActionSocketSystemName = systemName;
129    }
130
131    public FemaleAnalogExpressionSocket getAnalogExpressionSocket() {
132        return _analogExpressionSocket;
133    }
134
135    public String getAnalogExpressionSocketSystemName() {
136        return _analogExpressionSocketSystemName;
137    }
138
139    public void setAnalogExpressionSocketSystemName(String systemName) {
140        _analogExpressionSocketSystemName = systemName;
141    }
142
143    /** {@inheritDoc} */
144    @Override
145    public void setup() {
146        try {
147            if (!_analogExpressionSocket.isConnected()
148                    || !_analogExpressionSocket.getConnectedSocket().getSystemName()
149                            .equals(_analogExpressionSocketSystemName)) {
150                
151                String socketSystemName = _analogExpressionSocketSystemName;
152                
153                _analogExpressionSocket.disconnect();
154                
155                if (socketSystemName != null) {
156                    MaleSocket maleSocket =
157                            InstanceManager.getDefault(AnalogExpressionManager.class)
158                                    .getBySystemName(socketSystemName);
159                    if (maleSocket != null) {
160                        _analogExpressionSocket.connect(maleSocket);
161                        maleSocket.setup();
162                    } else {
163                        log.error("cannot load analog expression {}", socketSystemName);
164                    }
165                }
166            } else {
167                _analogExpressionSocket.getConnectedSocket().setup();
168            }
169            
170            if (!_analogActionSocket.isConnected()
171                    || !_analogActionSocket.getConnectedSocket().getSystemName()
172                            .equals(_analogActionSocketSystemName)) {
173                
174                String socketSystemName = _analogActionSocketSystemName;
175                
176                _analogActionSocket.disconnect();
177                
178                if (socketSystemName != null) {
179                    MaleSocket maleSocket =
180                            InstanceManager.getDefault(AnalogActionManager.class)
181                                    .getBySystemName(socketSystemName);
182                    if (maleSocket != null) {
183                        _analogActionSocket.connect(maleSocket);
184                        maleSocket.setup();
185                    } else {
186                        log.error("cannot load analog action {}", socketSystemName);
187                    }
188                }
189            } else {
190                _analogActionSocket.getConnectedSocket().setup();
191            }
192        } catch (SocketAlreadyConnectedException ex) {
193            // This shouldn't happen and is a runtime error if it does.
194            throw new RuntimeException("socket is already connected");
195        }
196    }
197    
198    /** {@inheritDoc} */
199    @Override
200    public void registerListenersForThisClass() {
201    }
202    
203    /** {@inheritDoc} */
204    @Override
205    public void unregisterListenersForThisClass() {
206    }
207    
208    /** {@inheritDoc} */
209    @Override
210    public void disposeMe() {
211    }
212    
213    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DoAnalogAction.class);
214    
215}