001package jmri.jmrit.logixng.actions.swing;
002
003import java.awt.*;
004import java.awt.event.ActionEvent;
005import java.util.*;
006import java.util.List;
007
008import javax.annotation.CheckForNull;
009import javax.annotation.Nonnull;
010import javax.swing.*;
011import javax.swing.table.TableColumn;
012
013import jmri.InstanceManager;
014import jmri.jmrit.logixng.*;
015import jmri.jmrit.logixng.SymbolTable.InitialValueType;
016import jmri.jmrit.logixng.actions.WebRequest;
017import jmri.jmrit.logixng.actions.WebRequest.RequestMethodType;
018import jmri.jmrit.logixng.util.parser.*;
019import jmri.jmrit.logixng.util.swing.LogixNG_SelectCharsetSwing;
020import jmri.jmrit.logixng.util.swing.LogixNG_SelectEnumSwing;
021import jmri.jmrit.logixng.util.swing.LogixNG_SelectStringSwing;
022import jmri.util.table.ButtonEditor;
023import jmri.util.table.ButtonRenderer;
024
025/**
026 * Configures an WebRequest object with a Swing JPanel.
027 *
028 * @author Daniel Bergqvist Copyright (C) 2021
029 */
030public class WebRequestSwing extends AbstractDigitalActionSwing {
031
032    private JTabbedPane _tabbedPane;
033    private JPanel _panelUrl;
034    private JPanel _panelCharset;
035    private JPanel _panelRequestMethod;
036    private JPanel _panelUserAgent;
037
038    private LogixNG_SelectStringSwing _selectUrlSwing;
039    private LogixNG_SelectCharsetSwing _selectCharsetSwing;
040    private LogixNG_SelectEnumSwing<RequestMethodType> _selectRequestMethodSwing;
041    private LogixNG_SelectStringSwing _selectUserAgentSwing;
042
043    private JTextField _localVariableForResponseCodeTextField;
044    private JTextField _localVariableForReplyContentTextField;
045    private JTextField _localVariableForCookiesTextField;
046
047    private JTable _logDataTable;
048    private WebRequestTableModel _logDataTableModel;
049
050
051    @Override
052    protected void createPanel(@CheckForNull Base object, @Nonnull JPanel buttonPanel) {
053        if ((object != null) && !(object instanceof WebRequest)) {
054            throw new IllegalArgumentException("object must be an WebRequest but is a: "+object.getClass().getName());
055        }
056
057        _tabbedPane = new JTabbedPane();
058        _panelUrl = new JPanel();
059        _panelCharset = new JPanel();
060        _panelRequestMethod = new JPanel();
061        _panelUserAgent = new JPanel();
062
063        _selectUrlSwing = new LogixNG_SelectStringSwing(getJDialog(), this);
064        _selectCharsetSwing = new LogixNG_SelectCharsetSwing(getJDialog(), this);
065        _selectRequestMethodSwing = new LogixNG_SelectEnumSwing<>(getJDialog(), this);
066        _selectUserAgentSwing = new LogixNG_SelectStringSwing(getJDialog(), this);
067
068        WebRequest action = (WebRequest)object;
069
070        panel = new JPanel();
071        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
072
073        JPanel tabbedPaneUrl;
074        JPanel tabbedPaneCharset;
075        JPanel tabbedPaneRequestMethod;
076        JPanel tabbedPaneUserAgent;
077
078        if (action != null) {
079            tabbedPaneUrl = _selectUrlSwing.createPanel(action.getSelectUrl());
080            tabbedPaneCharset = _selectCharsetSwing.createPanel(action.getSelectCharset());
081            tabbedPaneRequestMethod = _selectRequestMethodSwing.createPanel(action.getSelectRequestMethod(), RequestMethodType.values());
082            tabbedPaneUserAgent = _selectUserAgentSwing.createPanel(action.getSelectUserAgent());
083        } else {
084            tabbedPaneUrl = _selectUrlSwing.createPanel(null);
085            tabbedPaneCharset = _selectCharsetSwing.createPanel(null);
086            tabbedPaneRequestMethod = _selectRequestMethodSwing.createPanel(null, RequestMethodType.values());
087            tabbedPaneUserAgent = _selectUserAgentSwing.createPanel(null);
088        }
089
090
091        JLabel selectUrlLabel = new JLabel(Bundle.getMessage("WebRequestSwing_Url"));
092        selectUrlLabel.setLabelFor(tabbedPaneUrl);
093
094        JLabel selectCharsetLabel = new JLabel(Bundle.getMessage("WebRequestSwing_Charset"));
095        selectCharsetLabel.setLabelFor(tabbedPaneCharset);
096
097        JLabel selectRequestMethodLabel = new JLabel(Bundle.getMessage("WebRequestSwing_RequestMethod"));
098        selectRequestMethodLabel.setLabelFor(tabbedPaneRequestMethod);
099
100        JLabel selectUserAgentLabel = new JLabel(Bundle.getMessage("WebRequestSwing_UserAgent"));
101        selectUserAgentLabel.setLabelFor(tabbedPaneUserAgent);
102
103        _panelUrl.add(selectUrlLabel);
104        _panelUrl.add(tabbedPaneUrl);
105
106        _panelCharset.add(selectCharsetLabel);
107        _panelCharset.add(tabbedPaneCharset);
108
109        _panelRequestMethod.add(selectRequestMethodLabel);
110        _panelRequestMethod.add(tabbedPaneRequestMethod);
111
112        _panelUserAgent.add(selectUserAgentLabel);
113        _panelUserAgent.add(tabbedPaneUserAgent);
114
115        _tabbedPane.addTab(Bundle.getMessage("WebRequestSwing_Url"), _panelUrl);
116        _tabbedPane.addTab(Bundle.getMessage("WebRequestSwing_Charset"), _panelCharset);
117        _tabbedPane.addTab(Bundle.getMessage("WebRequestSwing_RequestMethod"), _panelRequestMethod);
118        _tabbedPane.addTab(Bundle.getMessage("WebRequestSwing_UserAgent"), _panelUserAgent);
119
120        JLabel localVariableForResponseCodeLabel = new JLabel(Bundle.getMessage("WebRequestSwing_LocalVariableForResponseCode"));
121        _localVariableForResponseCodeTextField = new JTextField();
122        _localVariableForResponseCodeTextField.setColumns(30);
123
124        JLabel localVariableForReplyContentLabel = new JLabel(Bundle.getMessage("WebRequestSwing_LocalVariableForReplyContent"));
125        _localVariableForReplyContentTextField = new JTextField();
126        _localVariableForReplyContentTextField.setColumns(30);
127
128        JLabel localVariableForCookiesLabel = new JLabel(Bundle.getMessage("WebRequestSwing_LocalVariableForCookies"));
129        _localVariableForCookiesTextField = new JTextField();
130        _localVariableForCookiesTextField.setColumns(30);
131
132
133        _logDataTable = new JTable();
134
135        if (action != null) {
136            List<WebRequest.Parameter> dataList
137                    = new ArrayList<>(action.getParameters());
138
139            _logDataTableModel = new WebRequestTableModel(dataList);
140        } else {
141            _logDataTableModel = new WebRequestTableModel(null);
142        }
143
144        _logDataTable.setModel(_logDataTableModel);
145        _logDataTable.setDefaultRenderer(InitialValueType.class,
146                new WebRequestTableModel.CellRenderer());
147        _logDataTable.setDefaultEditor(InitialValueType.class,
148                new WebRequestTableModel.DataTypeCellEditor());
149        _logDataTableModel.setColumnsForComboBoxes(_logDataTable);
150        _logDataTable.setDefaultRenderer(JButton.class, new ButtonRenderer());
151        _logDataTable.setDefaultEditor(JButton.class, new ButtonEditor(new JButton()));
152
153        JButton testButton = new JButton("XXXXXX");  // NOI18N
154        _logDataTable.setRowHeight(testButton.getPreferredSize().height);
155        TableColumn deleteColumn = _logDataTable.getColumnModel()
156                .getColumn(WebRequestTableModel.COLUMN_DUMMY);
157        deleteColumn.setMinWidth(testButton.getPreferredSize().width);
158        deleteColumn.setMaxWidth(testButton.getPreferredSize().width);
159        deleteColumn.setResizable(false);
160
161        // The dummy column is used to be able to force update of the
162        // other columns when the panel is closed.
163        TableColumn dummyColumn = _logDataTable.getColumnModel()
164                .getColumn(WebRequestTableModel.COLUMN_DUMMY);
165        dummyColumn.setMinWidth(0);
166        dummyColumn.setPreferredWidth(0);
167        dummyColumn.setMaxWidth(0);
168
169        JScrollPane scrollpane = new JScrollPane(_logDataTable);
170        scrollpane.setPreferredSize(new Dimension(400, 200));
171
172        // Add parameter
173        JButton add = new JButton(Bundle.getMessage("WebRequest_TableAdd"));
174        buttonPanel.add(add);
175        add.addActionListener((ActionEvent e) -> {
176            _logDataTableModel.add();
177        });
178
179        JLabel parametersLabel = new JLabel(Bundle.getMessage("WebRequest_Parameters"));
180        parametersLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
181        scrollpane.setAlignmentX(Component.LEFT_ALIGNMENT);
182
183        JPanel tablePanel = new JPanel();
184        tablePanel.setLayout(new BoxLayout(tablePanel, BoxLayout.PAGE_AXIS));
185        tablePanel.add(parametersLabel);
186        tablePanel.add(scrollpane);
187
188
189
190        panel.setLayout(new GridBagLayout());
191        GridBagConstraints constraint = new GridBagConstraints();
192        Insets defaultInsets = constraint.insets;
193        constraint.gridwidth = 1;
194        constraint.gridheight = 1;
195        constraint.gridx = 0;
196        constraint.gridy = 0;
197        constraint.gridwidth = 2;
198        constraint.anchor = GridBagConstraints.CENTER;
199        panel.add(_tabbedPane, constraint);
200        constraint.gridy = 1;
201        constraint.insets = new Insets(10,0,10,0);
202        panel.add(tablePanel, constraint);
203
204        constraint.gridwidth = 1;
205        constraint.gridy = 2;
206        constraint.anchor = GridBagConstraints.EAST;
207        constraint.insets = defaultInsets;
208        panel.add(localVariableForResponseCodeLabel, constraint);
209        localVariableForResponseCodeLabel.setLabelFor(_localVariableForResponseCodeTextField);
210        constraint.gridy = 3;
211        panel.add(localVariableForReplyContentLabel, constraint);
212        localVariableForReplyContentLabel.setLabelFor(_localVariableForReplyContentTextField);
213        constraint.gridy = 4;
214        panel.add(localVariableForCookiesLabel, constraint);
215        localVariableForCookiesLabel.setLabelFor(_localVariableForCookiesTextField);
216
217        constraint.gridx = 1;
218        constraint.gridy = 2;
219        constraint.anchor = GridBagConstraints.EAST;
220        panel.add(_localVariableForResponseCodeTextField, constraint);
221        constraint.gridy = 3;
222        panel.add(_localVariableForReplyContentTextField, constraint);
223        constraint.gridy = 4;
224        panel.add(_localVariableForCookiesTextField, constraint);
225
226
227        if (action != null) {
228            _localVariableForResponseCodeTextField.setText(action.getLocalVariableForResponseCode());
229            _localVariableForReplyContentTextField.setText(action.getLocalVariableForReplyContent());
230            _localVariableForCookiesTextField.setText(action.getLocalVariableForCookies());
231        }
232    }
233
234    /** {@inheritDoc} */
235    @Override
236    public boolean validate(@Nonnull List<String> errorMessages) {
237        // Create a temporary action to test formula
238        WebRequest action = new WebRequest("IQDA1", null);
239
240        _selectUrlSwing.validate(action.getSelectUrl(), errorMessages);
241        _selectCharsetSwing.validate(action.getSelectCharset(), errorMessages);
242        _selectRequestMethodSwing.validate(action.getSelectRequestMethod(), errorMessages);
243        _selectUserAgentSwing.validate(action.getSelectUserAgent(), errorMessages);
244
245        for (WebRequest.Parameter data : _logDataTableModel.getDataList()) {
246            if (data.getType() == InitialValueType.Formula) {
247                try {
248                    Map<String, Variable> variables = new HashMap<>();
249                    RecursiveDescentParser parser = new RecursiveDescentParser(variables);
250                    parser.parseExpression(data.getData());
251                } catch (ParserException e) {
252                    errorMessages.add(e.getLocalizedMessage());
253                }
254            }
255        }
256
257        return errorMessages.isEmpty();
258    }
259
260    /** {@inheritDoc} */
261    @Override
262    public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) {
263        WebRequest action = new WebRequest(systemName, userName);
264        updateObject(action);
265        return InstanceManager.getDefault(DigitalActionManager.class).registerAction(action);
266    }
267
268    /** {@inheritDoc} */
269    @Override
270    public void updateObject(@Nonnull Base object) {
271        if (!(object instanceof WebRequest)) {
272            throw new IllegalArgumentException("object must be an WebRequest but is a: "+object.getClass().getName());
273        }
274
275        WebRequest action = (WebRequest)object;
276
277        _selectUrlSwing.updateObject(action.getSelectUrl());
278        _selectCharsetSwing.updateObject(action.getSelectCharset());
279        _selectRequestMethodSwing.updateObject(action.getSelectRequestMethod());
280        _selectUserAgentSwing.updateObject(action.getSelectUserAgent());
281
282        action.setLocalVariableForResponseCode(_localVariableForResponseCodeTextField.getText());
283        action.setLocalVariableForReplyContent(_localVariableForReplyContentTextField.getText());
284        action.setLocalVariableForCookies(_localVariableForCookiesTextField.getText());
285
286        // Do this to force update of the table
287        _logDataTable.editCellAt(0, 2);
288
289        action.getParameters().clear();
290
291        for (WebRequest.Parameter data : _logDataTableModel.getDataList()) {
292            action.getParameters().add(data);
293        }
294    }
295
296    /** {@inheritDoc} */
297    @Override
298    public String toString() {
299        return Bundle.getMessage("WebRequest_Short");
300    }
301
302    @Override
303    public void dispose() {
304        _selectUrlSwing.dispose();
305        _selectCharsetSwing.dispose();
306        _selectRequestMethodSwing.dispose();
307        _selectUserAgentSwing.dispose();
308    }
309
310}