001package jmri.jmrix.mqtt.logixng;
002
003import jmri.jmrit.logixng.actions.*;
004
005import java.beans.PropertyChangeEvent;
006import java.beans.PropertyChangeListener;
007import java.util.*;
008
009import jmri.*;
010import jmri.jmrit.logixng.*;
011import jmri.jmrit.logixng.util.LogixNG_SelectString;
012import jmri.jmrit.logixng.util.parser.ParserException;
013import jmri.jmrix.mqtt.MqttSystemConnectionMemo;
014import jmri.util.ThreadingUtil;
015
016/**
017 * This action publishes a message to MQTT.
018 *
019 * @author Daniel Bergqvist Copyright 2022
020 */
021public class Publish extends AbstractDigitalAction
022        implements PropertyChangeListener {
023
024    private final LogixNG_SelectString _selectTopic =
025            new LogixNG_SelectString(this, this);
026    private final LogixNG_SelectString _selectMessage =
027            new LogixNG_SelectString(this, this);
028
029    private MqttSystemConnectionMemo _memo;
030    
031    private Retain _retain;
032
033
034    public Publish(String sys, String user, MqttSystemConnectionMemo memo)
035            throws BadUserNameException, BadSystemNameException {
036        super(sys, user);
037        _memo = memo;
038        _retain = Retain.Default;
039    }
040
041    @Override
042    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws ParserException {
043        DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.class);
044        String sysName = systemNames.get(getSystemName());
045        String userName = userNames.get(getSystemName());
046        if (sysName == null) sysName = manager.getAutoSystemName();
047        Publish copy = new Publish(sysName, userName, _memo);
048        copy.setComment(getComment());
049        _selectTopic.copy(copy._selectTopic);
050        _selectMessage.copy(copy._selectMessage);
051        copy.setRetain(_retain);
052        return manager.registerAction(copy);
053    }
054
055    public void setMemo(MqttSystemConnectionMemo memo) {
056        assertListenersAreNotRegistered(log, "setMemo");
057        _memo = memo;
058    }
059
060    public MqttSystemConnectionMemo getMemo() {
061        return _memo;
062    }
063
064    public LogixNG_SelectString getSelectTopic() {
065        return _selectTopic;
066    }
067
068    public LogixNG_SelectString getSelectMessage() {
069        return _selectMessage;
070    }
071
072    public void setRetain(Retain retain) {
073        assertListenersAreNotRegistered(log, "setRetain");
074        _retain = retain;
075    }
076
077    public Retain getRetain() {
078        return _retain;
079    }
080
081    /** {@inheritDoc} */
082    @Override
083    public Category getCategory() {
084        return Category.ITEM;
085    }
086
087    /** {@inheritDoc} */
088    @Override
089    public void execute() throws JmriException {
090
091        String topic = _selectTopic.evaluateValue(getConditionalNG());
092        String data = _selectMessage.evaluateValue(getConditionalNG());
093        
094        boolean retain = _retain.getRetainValue(_memo);
095
096        ThreadingUtil.runOnLayoutWithJmriException(() -> {
097            _memo.getMqttAdapter().publish(topic, data, retain);
098        });
099    }
100
101    @Override
102    public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException {
103        throw new UnsupportedOperationException("Not supported.");
104    }
105
106    @Override
107    public int getChildCount() {
108        return 0;
109    }
110
111    @Override
112    public String getShortDescription(Locale locale) {
113        return Bundle.getMessage(locale, "Publish_Short");
114    }
115
116    @Override
117    public String getLongDescription(Locale locale) {
118        return Bundle.getMessage(locale, "Publish_Long",
119                _selectTopic.getDescription(locale),
120                _selectMessage.getDescription(locale),
121                _retain.toString());
122    }
123
124    /** {@inheritDoc} */
125    @Override
126    public void setup() {
127        // Do nothing
128    }
129
130    /** {@inheritDoc} */
131    @Override
132    public void registerListenersForThisClass() {
133        _selectTopic.registerListeners();
134        _selectMessage.registerListeners();
135    }
136
137    /** {@inheritDoc} */
138    @Override
139    public void unregisterListenersForThisClass() {
140        _selectTopic.unregisterListeners();
141        _selectMessage.unregisterListeners();
142    }
143
144    /** {@inheritDoc} */
145    @Override
146    public void propertyChange(PropertyChangeEvent evt) {
147        getConditionalNG().execute();
148    }
149
150    /** {@inheritDoc} */
151    @Override
152    public void disposeMe() {
153    }
154
155
156    public enum Retain {
157        Default(Bundle.getMessage("Publish_Retain_Default")),
158        Yes(Bundle.getMessage("Publish_Retain_Yes")),
159        No(Bundle.getMessage("Publish_Retain_No"));
160
161        private final String _text;
162
163        private Retain(String text) {
164            this._text = text;
165        }
166        
167        public boolean getRetainValue(MqttSystemConnectionMemo memo) {
168            switch (this) {
169                case Default:
170                    return memo.getMqttAdapter().retained;
171                case Yes:
172                    return true;
173                case No:
174                    return false;
175                default:
176                    throw new IllegalArgumentException("invalid retain");
177            }
178        }
179
180        @Override
181        public String toString() {
182            return _text;
183        }
184
185    }
186
187
188    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Publish.class);
189
190}