Commit 4cc84b6399aaded5f095337d6a3394ca5ab443f5

Authored by Nathanael Jourdane
1 parent 4a03be16
Exists in master

Add the possibility to send queries to the selected service.

src/main/java/eu/omp/irap/vespa/epntapclient/EpnTapMainApp.java
... ... @@ -49,7 +49,7 @@ public class EpnTapMainApp {
49 49 frame.setContentPane(epnTapControl.getView());
50 50 frame.setVisible(true);
51 51 // frame.pack();
52   - frame.setSize(800, 600);
  52 + frame.setSize(1000, 600);
53 53 frame.setLocationRelativeTo(null);
54 54 }
55 55 });
... ...
src/main/java/eu/omp/irap/vespa/epntapclient/controller/EpnTapController.java
... ... @@ -17,6 +17,7 @@
17 17 package eu.omp.irap.vespa.epntapclient.controller;
18 18  
19 19 import eu.omp.irap.vespa.epntapclient.utils.Const;
  20 +import eu.omp.irap.vespa.epntapclient.utils.Log;
20 21 import eu.omp.irap.vespa.epntapclient.utils.Queries;
21 22 import eu.omp.irap.vespa.epntapclient.view.EpnTapMainView;
22 23 import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableController;
... ... @@ -29,27 +30,29 @@ public class EpnTapController {
29 30 /** The view of EPN-TAP application. */
30 31 EpnTapMainView view;
31 32  
  33 + /** The controller of the VOTable displaying the list of services. */
  34 + VOTableController servicesController;
  35 +
32 36 /** The controller of the VOTable displaying the query results. */
33 37 VOTableController resultsController;
34 38  
35   - /** The controller of the VOTable displaying the list of services. */
36   - VOTableController servicesController;
  39 + /** The URL of the service selected by the user on the services list panel. */
  40 + String selectedServiceURL;
37 41  
38 42 /**
39 43 * Method constructor
40 44 */
41 45 public EpnTapController() {
  46 + // TODO: Get only *EPN* TAP services
42 47 servicesController = new VOTableController(Const.DEFAULT_REGISTRY_URL, "ADQL",
43 48 Queries.GET_TAP_SERVICES);
44 49  
45   - VOTableView serviceView = servicesController.getView();
46   -
47   - view = new EpnTapMainView(this, serviceView);
  50 + resultsController = new VOTableController();
48 51  
49   - String[] rColumns = { "result name", "result value" };
50   - String[][] rValues = { { "r1", "r2" }, { "123", "456" } };
51   -
52   - view.fillResults(rColumns, rValues);
  52 + VOTableView serviceView = servicesController.getView();
  53 + VOTableView resultsView = resultsController.getView();
  54 + view = new EpnTapMainView(this, serviceView, resultsView);
  55 + setSelectedService(0);
53 56 }
54 57  
55 58 /**
... ... @@ -72,4 +75,24 @@ public class EpnTapController {
72 75 public VOTableController getServicesController() {
73 76 return servicesController;
74 77 }
  78 +
  79 + /**
  80 + * @param row The row selected by the user on the Jtable.
  81 + */
  82 + public void setSelectedService(int row) {
  83 + String serviceURL = (String) view.getServices().getValueAt(1, row);
  84 + if (!serviceURL.equals(selectedServiceURL)) {
  85 + selectedServiceURL = serviceURL;
  86 + Log.LOGGER.info("Selected service URL: " + selectedServiceURL);
  87 + }
  88 + }
  89 +
  90 + /**
  91 + * @param query The query to send to the selected service.
  92 + * @throws Exception If the Table can not be filled.
  93 + */
  94 + public void sendQuery(String query) throws Exception {
  95 + Log.LOGGER.info("Sending query: " + query + " on " + selectedServiceURL);
  96 + resultsController.fillTable(selectedServiceURL, "ADQL", query);
  97 + }
75 98 }
... ...
src/main/java/eu/omp/irap/vespa/epntapclient/utils/Queries.java
... ... @@ -49,4 +49,7 @@ public class Queries {
49 49 /** Minimal query to get TAP all services of the registry, using GloTS. */
50 50 public static final String GET_TAP_SERVICES = "SELECT ivoid, accessurl FROM glots.services";
51 51  
  52 + /** A sample query for tests. */
  53 + public static final String SAMPLE_AMDA_QUERY = "SELECT TOP 5 index, resource_type, time_min, time_max FROM amdadb.epn_core";
  54 +
52 55 }
... ...
src/main/java/eu/omp/irap/vespa/epntapclient/view/EpnTapMainView.java
... ... @@ -17,6 +17,12 @@
17 17 package eu.omp.irap.vespa.epntapclient.view;
18 18  
19 19 import java.awt.BorderLayout;
  20 +import java.awt.event.KeyAdapter;
  21 +import java.awt.event.KeyEvent;
  22 +import java.awt.event.KeyListener;
  23 +import java.awt.event.MouseAdapter;
  24 +import java.awt.event.MouseEvent;
  25 +import java.awt.event.MouseListener;
20 26  
21 27 import javax.swing.JOptionPane;
22 28 import javax.swing.JPanel;
... ... @@ -41,36 +47,48 @@ public class EpnTapMainView extends JPanel {
41 47 /** The JPanel where the user put requests. */
42 48 private RequestView requestView;
43 49  
  50 + /** The main EPN-TAP main controller */
  51 + private EpnTapController controller;
  52 +
44 53 /**
45 54 * The constructor of the view.
46 55 *
47 56 * @param controller The EPN-TAP controller, allowing the EPN-TAP view to send events.
48 57 * @param servicesView The JPanel representing the table of services.
  58 + * @param resultsView The JPanel representing the table of results.
49 59 */
50   - public EpnTapMainView(EpnTapController controller, VOTableView servicesView) {
  60 + public EpnTapMainView(EpnTapController controller, VOTableView servicesView,
  61 + VOTableView resultsView) {
  62 + this.controller = controller;
51 63 this.servicesView = servicesView;
52   - resultsView = new VOTableView(controller.getResultsController());
  64 + this.resultsView = resultsView;
53 65 this.requestView = new RequestView(this);
54 66  
55 67 buildWindow();
56   - }
57 68  
58   - /**
59   - * @param columns The name of each column to fill the Service table.
60   - * @param values A 2D array, where the first dimension represents the rows of the Services
61   - * table. The second one represents each element, in the same order as the `columns`.
62   - */
63   - public void fillServices(String[] columns, Object[][] values) {
64   - servicesView.buildArray(columns, values);
  69 + // TODO: support multi-selection
  70 + KeyListener tableKeyListener = new KeyAdapter() {
  71 + @Override
  72 + public void keyPressed(KeyEvent e) {
  73 + controller.setSelectedService(servicesView.getTable().getSelectedRow());
  74 + }
  75 + };
  76 + MouseListener tableMouseListener = new MouseAdapter() {
  77 + @Override
  78 + public void mouseClicked(MouseEvent e) {
  79 + controller.setSelectedService(servicesView.getTable().getSelectedRow());
  80 + }
  81 + };
  82 +
  83 + servicesView.getTable().addKeyListener(tableKeyListener);
  84 + servicesView.getTable().addMouseListener(tableMouseListener);
65 85 }
66 86  
67 87 /**
68   - * @param columns The name of each column to fill the Results table.
69   - * @param values A 2D array, where the first dimension represents the rows of the Results table.
70   - * The second one represents each element, in the same order as the `columns`.
  88 + * @return The main EPNT-TAP controller.
71 89 */
72   - public void fillResults(String[] columns, Object[][] values) {
73   - resultsView.buildArray(columns, values);
  90 + public EpnTapController getController() {
  91 + return controller;
74 92 }
75 93  
76 94 /**
... ... @@ -107,7 +125,8 @@ public class EpnTapMainView extends JPanel {
107 125 * @param message The message of the error.
108 126 */
109 127 public void displayError(String title, String message) {
110   - JOptionPane.showMessageDialog(this, message, title, JOptionPane.ERROR_MESSAGE);
  128 + JOptionPane.showMessageDialog(this, message, title,
  129 + JOptionPane.ERROR_MESSAGE);
111 130 }
112 131  
113 132 }
... ...
src/main/java/eu/omp/irap/vespa/epntapclient/view/RequestView.java
... ... @@ -17,15 +17,21 @@
17 17 package eu.omp.irap.vespa.epntapclient.view;
18 18  
19 19 import java.awt.BorderLayout;
  20 +import java.awt.event.ActionEvent;
  21 +import java.awt.event.ActionListener;
20 22  
  23 +import javax.swing.JButton;
21 24 import javax.swing.JLabel;
22 25 import javax.swing.JPanel;
23 26 import javax.swing.JTextArea;
24 27  
  28 +import eu.omp.irap.vespa.epntapclient.utils.Log;
  29 +import eu.omp.irap.vespa.epntapclient.utils.Queries;
  30 +
25 31 /**
26 32 * @author N. Jourdane
27 33 */
28   -public class RequestView extends JPanel {
  34 +public class RequestView extends JPanel implements ActionListener {
29 35  
30 36 /** The serial version UID (affected with a random number). */
31 37 private static final long serialVersionUID = 1262856496809315405L;
... ... @@ -33,11 +39,8 @@ public class RequestView extends JPanel {
33 39 /** The EPN-TAP main view. */
34 40 EpnTapMainView mainView;
35 41  
36   - /** The text area where the user put its requests. */
37   - private JTextArea queryArea;
38   -
39   - /** The text area where the user put its requests. */
40   - private JLabel queryTitle;
  42 + /** The text area where the user put the query. */
  43 + JTextArea queryArea;
41 44  
42 45 /**
43 46 * Method constructor
... ... @@ -46,12 +49,28 @@ public class RequestView extends JPanel {
46 49 */
47 50 public RequestView(EpnTapMainView mainView) {
48 51 this.mainView = mainView;
49   - queryArea = new JTextArea("");
50   - queryTitle = new JLabel("Query for the selected service");
51   -
  52 + JLabel queryTitle = new JLabel("Query for the selected service");
  53 + queryArea = new JTextArea(Queries.SAMPLE_AMDA_QUERY);
  54 + JButton button = new JButton("Send query");
  55 + button.setName("btnSend");
52 56 setLayout(new BorderLayout());
  57 +
53 58 this.add(queryTitle, BorderLayout.NORTH);
54 59 this.add(queryArea, BorderLayout.CENTER);
  60 + this.add(button, BorderLayout.SOUTH);
  61 +
  62 + button.addActionListener(this);
  63 + }
  64 +
  65 + @Override
  66 + public void actionPerformed(ActionEvent e) {
  67 + if (((JButton) e.getSource()).getName() == "btnSend") {
  68 + try {
  69 + mainView.getController().sendQuery(queryArea.getText());
  70 + } catch (Exception e1) {
  71 + Log.LOGGER.severe(e1.getMessage());
  72 + }
  73 + }
55 74 }
56 75  
57 76 }
... ...
src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableConnection.java
... ... @@ -56,13 +56,14 @@ public class VOTableConnection {
56 56 int responseCode = -1;
57 57 String uri = targetURL + "/sync";
58 58 String parameters = "REQUEST=doQuery&LANG=" + queryLanguage + "&QUERY=";
59   - parameters += URLEncoder.encode(query, Const.CHARACTER_SET);
  59 + parameters += URLEncoder.encode(query, Const.CHARACTER_SET).replace("+", "%20")
  60 + .replace(".", "%2E").replace("-", "%2D").replace("*", "%2A").replace("_", "%5F");
60 61  
61 62 Log.LOGGER.info("request: " + uri + "?" + parameters);
62 63 try {
63 64 responseCode = VOTableConnection.sendGet(uri, parameters, voTablePath);
64 65 } catch (Exception e1) {
65   - throw new Exception("Can not send the specified query: " + uri + "?" + query, e1);
  66 + throw new Exception("Can not send the request: " + uri + "?" + parameters, e1);
66 67 }
67 68 if (responseCode != 200) {
68 69 throw new Exception("Bad response code for the query: " + query);
... ... @@ -85,6 +86,7 @@ public class VOTableConnection {
85 86 URL obj = new URL(url + "?" + urlParameters);
86 87 int responseCode = -1;
87 88  
  89 + // TODO: Rรฉcupรฉrer le message d'erreur de la VOTable (VOTABLE/RESOURCE/INFO)
88 90 try {
89 91 HttpURLConnection con = (HttpURLConnection) obj.openConnection();
90 92 con.setRequestMethod("GET");
... ...
src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableController.java
... ... @@ -16,7 +16,6 @@
16 16  
17 17 package eu.omp.irap.vespa.epntapclient.votable.controller;
18 18  
19   -import eu.omp.irap.vespa.epntapclient.utils.Log;
20 19 import eu.omp.irap.vespa.epntapclient.votable.model.Table;
21 20 import eu.omp.irap.vespa.epntapclient.votable.model.VOTABLE;
22 21 import eu.omp.irap.vespa.epntapclient.votable.view.VOTableView;
... ... @@ -32,11 +31,12 @@ public class VOTableController {
32 31 /** The VOTable model */
33 32 VOTABLE voTable;
34 33  
35   - /** The table column selected by the user. */
36   - int selectedColumn;
37   -
38   - /** The table row selected by the user. */
39   - int selectedRow;
  34 + /**
  35 + * Method constructor
  36 + */
  37 + public VOTableController() {
  38 + view = new VOTableView();
  39 + }
40 40  
41 41 /**
42 42 * Method constructor
... ... @@ -44,13 +44,10 @@ public class VOTableController {
44 44 * @param voTablePath The path of the VOTable XML file.
45 45 */
46 46 public VOTableController(String voTablePath) {
47   - view = new VOTableView(this);
48   - selectedColumn = -1;
49   - selectedRow = -1;
  47 + view = new VOTableView();
50 48  
51 49 try {
52   - voTable = VOTableParser.parseVOTable(voTablePath);
53   - fillView();
  50 + fillTable(voTablePath);
54 51 } catch (Exception e) {
55 52 view.displayError("VOTable can not be displayed.\nReason:\n", e.getMessage());
56 53 }
... ... @@ -64,36 +61,51 @@ public class VOTableController {
64 61 * @param query The query to ask to the registry.
65 62 */
66 63 public VOTableController(String targetURL, String queryLanguage, String query) {
67   - view = new VOTableView(this);
68   - String voTablePath;
  64 + view = new VOTableView();
69 65  
70 66 try {
71   - voTablePath = VOTableConnection.sendQuery(targetURL, queryLanguage,
72   - query);
73   - voTable = VOTableParser.parseVOTable(voTablePath);
74   - fillView();
  67 + fillTable(VOTableConnection.sendQuery(targetURL, queryLanguage, query));
75 68 } catch (Exception e) {
76 69 view.displayError("VOTable can not be displayed.\nReason:\n", e.getMessage());
77 70 }
78 71 }
79 72  
  73 + public void fillTable(String targetURL, String queryLanguage, String query) throws Exception {
  74 + fillTable(VOTableConnection.sendQuery(targetURL, queryLanguage, query));
  75 + }
  76 +
80 77 /**
81   - * Fill the view with the VOTable data.
82   - *
83   - * @throws Exception If there are more than 1 resource or table in the VOTable.
  78 + * @param voTablePath The path of the VOTable file.
  79 + * @throws Exception If VOTable can not be parsed or there is more than one VOTable.
84 80 */
85   - private void fillView() throws Exception {
  81 + public void fillTable(String voTablePath) throws Exception {
  82 + try {
  83 + voTable = VOTableParser.parseVOTable(voTablePath);
  84 + } catch (Exception e) {
  85 + throw new Exception("Can not parse the VOTable.\n" + e.getMessage());
  86 + }
  87 +
86 88 // TODO: Traiter le cas oรน il y a plus d'une ressource et d'une table.
87   - if (voTable.getRESOURCE().size() != 1) {
88   - throw new Exception("VOTable with more than one resource are not yet supported.");
  89 + if (voTable.getRESOURCE().size() > 1) {
  90 + view.displayError("Several resources",
  91 + "VOTable with more than one resource are not yet supported. See VOTable file for debug:\n"
  92 + + voTablePath);
89 93 }
90   - if (voTable.getRESOURCE().get(0).getLINKAndTABLEOrRESOURCE().size() != 1) {
91   - throw new Exception("VOTable with more than one table are not yet supported.");
  94 + // TODO: iterate over all potential errors
  95 + if (voTable.getRESOURCE().get(0).getINFO().get(0).getValueAttribute().equals("ERROR")) {
  96 + view.displayError("Bad query", "There is an error on the query:\n"
  97 + + voTable.getRESOURCE().get(0).getINFO().get(0).getValue());
  98 + }
  99 + if (voTable.getRESOURCE().get(0).getLINKAndTABLEOrRESOURCE().size() > 1) {
  100 + view.displayError("Several tables",
  101 + "VOTable with more than one table are not yet supported. See VOTable file for debug:\n"
  102 + + voTablePath);
92 103 }
93 104 Table table = (Table) (voTable.getRESOURCE().get(0).getLINKAndTABLEOrRESOURCE().get(0));
  105 + System.out.println(table);
94 106  
95 107 VOTableDataParser dataParser = new VOTableDataParser(table);
96   - view.buildArray(dataParser.getColumnsName(), dataParser.getDataArray());
  108 + view.fillTable(dataParser.getColumnsName(), dataParser.getDataArray());
97 109 }
98 110  
99 111 /**
... ... @@ -102,12 +114,4 @@ public class VOTableController {
102 114 public VOTableView getView() {
103 115 return view;
104 116 }
105   -
106   - /**
107   - * @param selectedColumn The table column selected by the user.
108   - * @param selectedRow The table row selected by the user.
109   - */
110   - public void updateSelection(int selectedColumn, int selectedRow) {
111   - Log.LOGGER.info("Selection updated: [" + selectedColumn + " ; " + selectedRow + "]");
112   - }
113 117 }
... ...
src/main/java/eu/omp/irap/vespa/epntapclient/votable/view/VOTableView.java
... ... @@ -17,12 +17,6 @@
17 17 package eu.omp.irap.vespa.epntapclient.votable.view;
18 18  
19 19 import java.awt.BorderLayout;
20   -import java.awt.event.KeyAdapter;
21   -import java.awt.event.KeyEvent;
22   -import java.awt.event.KeyListener;
23   -import java.awt.event.MouseAdapter;
24   -import java.awt.event.MouseEvent;
25   -import java.awt.event.MouseListener;
26 20 import java.util.List;
27 21  
28 22 import javax.swing.JOptionPane;
... ... @@ -30,73 +24,41 @@ import javax.swing.JPanel;
30 24 import javax.swing.JScrollPane;
31 25 import javax.swing.JTable;
32 26 import javax.swing.ScrollPaneConstants;
33   -
34   -import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableController;
  27 +import javax.swing.event.TableModelEvent;
  28 +import javax.swing.event.TableModelListener;
  29 +import javax.swing.table.DefaultTableModel;
35 30  
36 31 /**
37 32 * The main class of the View of the application.
38 33 *
39 34 * @author N. Jourdane
40 35 */
41   -public class VOTableView extends JPanel {
  36 +public class VOTableView extends JPanel implements TableModelListener {
42 37  
43 38 /** The serial version UID (affected with a random number). */
44 39 private static final long serialVersionUID = -1233290271099283814L;
45 40  
46   - /** The VOTable controller, allowing the view to send events. */
47   - private VOTableController controller;
48   -
49 41 /** The JTable component where the data are displayed. */
50 42 private JTable table;
51 43  
52   - /**
53   - * Method constructor
54   - *
55   - * @param controller The VOTable controller, allowing the view to send events.
56   - */
57   - public VOTableView(VOTableController controller) {
58   - this.controller = controller;
59   - }
  44 + /** The DataModel representing the VOTable data in the JTable element. */
  45 + DefaultTableModel tableData;
60 46  
61 47 /**
62   - * Build and fill the GUI.
63   - *
64   - * @param keys The name of each column of the VOTable data.
65   - * @param values A list of arrays, representing the rows of the VOTable data. In each row,
66   - * elements are in the same order as `keys`.
67   - */
68   - public void buildArray(String[] keys, List<Object[]> values) {
69   - Object valuesArray[][] = values.toArray(new Object[values.size()][]);
70   - buildArray(keys, valuesArray);
71   - }
72   -
73   - /**
74   - * Build and fill the GUI.
75   - *
76   - * @param keys The name of each column of the VOTable data.
77   - * @param values A 2D array, where the first dimension represents the rows of the VOTable data.
78   - * The second one represents each element, in the same order as `keys`.
  48 + * Method constructor
79 49 */
80   - public void buildArray(String[] keys, Object[][] values) {
81   - table = new JTable(values, keys);
  50 + public VOTableView() {
  51 + tableData = new DefaultTableModel() {
  52 + /** The serial version UID (affected with a random number). */
  53 + private static final long serialVersionUID = 8195913508549662555L;
82 54  
83   - // TODO: support multi-selection
84   - KeyListener tableKeyListener = new KeyAdapter() {
85 55 @Override
86   - public void keyPressed(KeyEvent e) {
87   - updateSelection();
88   - }
89   - };
90   - MouseListener tableMouseListener = new MouseAdapter() {
91   - @Override
92   - public void mouseClicked(MouseEvent e) {
93   - updateSelection();
  56 + public boolean isCellEditable(int row, int column) {
  57 + return false;
94 58 }
95 59 };
96 60  
97   - table.addKeyListener(tableKeyListener);
98   - table.addMouseListener(tableMouseListener);
99   -
  61 + table = new JTable(tableData);
100 62 JScrollPane scrollPane = new JScrollPane(table);
101 63 scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
102 64 scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
... ... @@ -106,20 +68,48 @@ public class VOTableView extends JPanel {
106 68 }
107 69  
108 70 /**
109   - * This method is called on keyPressed and mouseClicked events on the JTable.
  71 + * Fill the JTable.
  72 + *
  73 + * @param columns the column names
  74 + * @param data The VoTable data displayed on the JTable
  75 + */
  76 + public void fillTable(String[] columns, List<Object[]> data) {
  77 + Object values[][] = data.toArray(new Object[data.size()][]);
  78 + tableData.setDataVector(values, columns);
  79 + table.setRowSelectionInterval(0, 0);
  80 + }
  81 +
  82 + /**
  83 + * @return The JTable element.
110 84 */
111   - void updateSelection() {
112   - controller.updateSelection(table.getSelectedColumn(), table.getSelectedRow());
  85 + public JTable getTable() {
  86 + return table;
  87 + }
  88 +
  89 + /**
  90 + * @param column The column index of the data to get.
  91 + * @param row The row index of the data to get.
  92 + * @return The element, can be a String, a integer or something else, according to the voTable
  93 + * content.
  94 + */
  95 + public Object getValueAt(int column, int row) {
  96 + return tableData.getValueAt(row, column);
113 97 }
114 98  
115 99 /**
116 100 * Display an error.
117 101 *
118   - * @param title The title of the error.
119   - * @param message The message of the error.
  102 + * @param title The title of the window.
  103 + * @param message The error message to display.
120 104 */
121 105 public void displayError(String title, String message) {
122 106 JOptionPane.showMessageDialog(this, message, title, JOptionPane.ERROR_MESSAGE);
123 107 }
124 108  
  109 + @Override
  110 + public void tableChanged(TableModelEvent e) {
  111 + if (e.getType() != TableModelEvent.UPDATE)
  112 + return;
  113 + }
  114 +
125 115 }
... ...