View Javadoc
1   package com.jsql.view.swing.panel.address;
2   
3   import com.jsql.util.CookiesUtil;
4   import com.jsql.util.LogLevelUtil;
5   import com.jsql.util.ParameterUtil;
6   import com.jsql.view.swing.panel.PanelAddressBar;
7   import org.apache.commons.lang3.StringUtils;
8   import org.apache.logging.log4j.LogManager;
9   import org.apache.logging.log4j.Logger;
10  
11  import javax.swing.*;
12  import java.awt.event.MouseAdapter;
13  import java.awt.event.MouseEvent;
14  import java.net.MalformedURLException;
15  import java.net.URI;
16  import java.net.URISyntaxException;
17  import java.util.AbstractMap;
18  import java.util.Arrays;
19  import java.util.regex.Pattern;
20  import java.util.stream.Stream;
21  
22  class TargetMouseAdapter extends MouseAdapter {
23  
24      private static final Logger LOGGER = LogManager.getRootLogger();
25  
26      private final PanelTrailingAddress panelTrailingAddress;
27      private final PanelAddressBar panelAddressBar;
28      private final JPopupMenu popupMenuTargets = new JPopupMenu();
29  
30      public TargetMouseAdapter(PanelTrailingAddress panelTrailingAddress, PanelAddressBar panelAddressBar) {
31          this.panelTrailingAddress = panelTrailingAddress;
32          this.panelAddressBar = panelAddressBar;
33      }
34  
35      @Override
36      public void mousePressed(MouseEvent event) {
37          this.popupMenuTargets.removeAll();
38          JRadioButtonMenuItem menuParamAuto = new JRadioButtonMenuItem(PanelTrailingAddress.PARAM_AUTO);
39          menuParamAuto.setActionCommand(PanelTrailingAddress.PARAM_AUTO);  // mock required when adding star: @ParameterUtil.controlInput
40          menuParamAuto.addActionListener(actionEvent ->
41              this.panelTrailingAddress.getLabelTarget().setText(menuParamAuto.getText())
42          );
43          this.popupMenuTargets.add(menuParamAuto);
44  
45          var rawQuery = this.panelAddressBar.getTextFieldAddress().getText().trim();
46          var rawRequest = this.panelAddressBar.getTextFieldRequest().getText().trim();
47          var rawHeader = this.panelAddressBar.getTextFieldHeader().getText().trim();
48  
49          var selection = this.panelTrailingAddress.getGroupRadio().getSelection();
50          String selectionCommand;  // effectively final
51          if (selection != null) {
52              selectionCommand = selection.getActionCommand();
53          } else {
54              selectionCommand = StringUtils.EMPTY;
55          }
56          this.panelTrailingAddress.setGroupRadio(new ButtonGroup());
57          this.panelTrailingAddress.getGroupRadio().add(menuParamAuto);
58          JMenu menuQuery = new JMenu("Query");
59          if (!rawQuery.isEmpty()) {
60              try {
61                  rawQuery = !rawQuery.matches("(?i)^\\w+://.*") ? "http://" + rawQuery : rawQuery;
62                  var url = new URI(rawQuery).toURL();
63                  if (url.getQuery() != null) {
64                      this.buildMenu(url.getQuery(), ParameterUtil.PREFIX_COMMAND_QUERY, selectionCommand, menuQuery);
65                  }
66              } catch (IllegalArgumentException | MalformedURLException | URISyntaxException e) {
67                  LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Incorrect URL: {}", e.getMessage());
68                  return;
69              }
70          }
71  
72          JMenu menuRequest = new JMenu("Request");
73          if (!rawRequest.isEmpty()) {
74              this.buildMenu(rawRequest, ParameterUtil.PREFIX_COMMAND_REQUEST, selectionCommand, menuRequest);
75          }
76  
77          JMenu menuHeader = new JMenu("Header");
78          if (!rawHeader.isEmpty()) {
79              this.buildMenuHeader(rawHeader, selectionCommand, menuHeader);
80          }
81  
82          Arrays.stream(this.popupMenuTargets.getComponents())
83              .map(JComponent.class::cast)
84              .forEach(c -> c.setEnabled(false));
85          menuParamAuto.setEnabled(true);
86          if (this.panelTrailingAddress.getGroupRadio().getSelection() == null) {
87              menuParamAuto.setSelected(true);
88              this.panelTrailingAddress.getLabelTarget().setText(menuParamAuto.getText());
89          }
90          menuQuery.setEnabled(menuQuery.getMenuComponentCount() > 0);
91          menuRequest.setEnabled(menuRequest.getMenuComponentCount() > 0);
92          menuHeader.setEnabled(menuHeader.getMenuComponentCount() > 0);
93  
94          if (
95              menuQuery.getMenuComponentCount() > 0
96              || menuRequest.getMenuComponentCount() > 0
97              || menuHeader.getMenuComponentCount() > 0
98          ) {
99              Arrays.stream(this.popupMenuTargets.getComponents())
100                 .map(JComponent.class::cast)
101                 .forEach(JComponent::updateUI);  // required: incorrect when dark/light mode switch
102             this.popupMenuTargets.updateUI();  // required: incorrect when dark/light mode switch
103             SwingUtilities.invokeLater(() -> {  // reduce flickering on linux
104                 this.popupMenuTargets.show(event.getComponent(), event.getComponent().getX(), 5 + event.getComponent().getY() + event.getComponent().getHeight());
105                 this.popupMenuTargets.setLocation(event.getComponent().getLocationOnScreen().x, 5 + event.getComponent().getLocationOnScreen().y + event.getComponent().getHeight());
106             });
107         } else {
108             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Missing parameter to inject");
109         }
110     }
111 
112     private void buildMenuHeader(String rawHeader, String selectionCommand, JMenu menuHeader) {
113         var listHeaders = Pattern.compile("\\\\r\\\\n")
114             .splitAsStream(rawHeader)
115             .map(keyValue -> Arrays.copyOf(keyValue.split(":"), 2))
116             .map(keyValue -> new AbstractMap.SimpleEntry<>(
117                 keyValue[0],
118                 keyValue[1] == null ? StringUtils.EMPTY : keyValue[1]
119             ))
120             .toList();
121         listHeaders.forEach(entry -> {
122             JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(entry.getKey());
123             menuItem.setSelected((ParameterUtil.PREFIX_COMMAND_HEADER + entry.getKey()).equals(selectionCommand));
124             menuItem.setActionCommand(ParameterUtil.PREFIX_COMMAND_HEADER + entry.getKey());
125             menuItem.addActionListener(actionEvent ->
126                 this.panelTrailingAddress.getLabelTarget().setText(entry.getKey())
127             );
128             this.panelTrailingAddress.getGroupRadio().add(menuItem);
129             menuHeader.add(menuItem);
130         });
131         if (listHeaders.stream().anyMatch(s -> CookiesUtil.COOKIE.equalsIgnoreCase(s.getKey()))) {
132             var cookies = listHeaders.stream()
133                 .filter(s -> CookiesUtil.COOKIE.equalsIgnoreCase(s.getKey()))
134                 .findFirst()
135                 .orElse(new AbstractMap.SimpleEntry<>(CookiesUtil.COOKIE, ""));
136             if (!cookies.getValue().trim().isEmpty()) {
137                 JMenu menuCookie = new JMenu(CookiesUtil.COOKIE);
138                 String[] cookieValues = StringUtils.split(cookies.getValue(), ";");
139                 Stream.of(cookieValues).forEach(cookie -> {
140                     String[] cookieEntry = StringUtils.split(cookie, "=");
141                     JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(cookieEntry[0].trim());
142                     menuItem.setSelected((ParameterUtil.PREFIX_COMMAND_COOKIE + cookieEntry[0].trim()).equals(selectionCommand));
143                     menuItem.setActionCommand(ParameterUtil.PREFIX_COMMAND_COOKIE + cookieEntry[0].trim());
144                     menuItem.addActionListener(actionEvent ->
145                             this.panelTrailingAddress.getLabelTarget().setText(cookieEntry[0].trim())
146                     );
147                     this.panelTrailingAddress.getGroupRadio().add(menuItem);
148                     menuCookie.add(menuItem);
149                 });
150                 menuHeader.addSeparator();
151                 menuHeader.add(menuCookie);
152             }
153         }
154         this.popupMenuTargets.add(menuHeader);
155     }
156 
157     private void buildMenu(String rawParams, String prefixCommand, String selectionCommand, JMenu menu) {
158         Pattern.compile("&").splitAsStream(rawParams)
159             .map(keyValue -> Arrays.copyOf(keyValue.split("="), 2))
160             .map(keyValue -> new AbstractMap.SimpleEntry<>(
161                 keyValue[0],
162                 keyValue[1] == null ? StringUtils.EMPTY : keyValue[1]
163             ))
164             .forEach(entry -> {
165                 JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(entry.getKey());
166                 menuItem.setSelected((prefixCommand + entry.getKey()).equals(selectionCommand));
167                 menuItem.setActionCommand(prefixCommand + entry.getKey());
168                 menuItem.addActionListener(actionEvent ->
169                     this.panelTrailingAddress.getLabelTarget().setText(entry.getKey())
170                 );
171                 this.panelTrailingAddress.getGroupRadio().add(menuItem);
172                 menu.add(menuItem);
173             });
174         this.popupMenuTargets.add(menu);
175     }
176 }