Commit 419a23a795dcc7b2733de724ca4ccfdb6415ed3e

Authored by Nathanael Jourdane
1 parent 5976415a
Exists in master

Add the possibility to query several services.

src/main/java/eu/omp/irap/vespa/epntapclient/RequestCtrl.java
@@ -36,8 +36,12 @@ public class RequestCtrl { @@ -36,8 +36,12 @@ public class RequestCtrl {
36 /** The URL of the resolver used for the `target name` field. */ 36 /** The URL of the resolver used for the `target name` field. */
37 private static final String RESOLVER_URL = "http://voparis-registry.obspm.fr/ssodnet/1/autocomplete"; 37 private static final String RESOLVER_URL = "http://voparis-registry.obspm.fr/ssodnet/1/autocomplete";
38 38
  39 + /** The text in the query to replaced by the actual table name. */
  40 + protected static final String TABLE_NAME_KEYWORD = "#tablename#";
  41 +
39 /** The query template to get granules. */ 42 /** The query template to get granules. */
40 - private static final String QUERY = "SELECT TOP %s target_name, target_class FROM %s%s"; 43 + private static final String QUERY = "SELECT DISTINCT TOP %s %s FROM " + TABLE_NAME_KEYWORD
  44 + + "%s";
41 45
42 /** The parameters fields for the request. */ 46 /** The parameters fields for the request. */
43 protected Map<String, Object> parameters = new HashMap<>(); 47 protected Map<String, Object> parameters = new HashMap<>();
@@ -63,10 +67,10 @@ public class RequestCtrl { @@ -63,10 +67,10 @@ public class RequestCtrl {
63 /** 67 /**
64 * Build an ADQL from the table name, the parameter values and the max results. 68 * Build an ADQL from the table name, the parameter values and the max results.
65 * 69 *
66 - * @param tableName The name of the table, to put in FROM keyword. 70 + * @param tableName The names of the tables, to put in the FROM keyword.
67 * @return The query. 71 * @return The query.
68 */ 72 */
69 - public String buildQuery(String tableName) { 73 + public String buildQuery(List<String> columnNames) {
70 StringJoiner addJoin = new StringJoiner(" AND "); 74 StringJoiner addJoin = new StringJoiner(" AND ");
71 for (Map.Entry<String, Object> param : parameters.entrySet()) { 75 for (Map.Entry<String, Object> param : parameters.entrySet()) {
72 if (param.getValue() instanceof ArrayList) { 76 if (param.getValue() instanceof ArrayList) {
@@ -84,8 +88,7 @@ public class RequestCtrl { @@ -84,8 +88,7 @@ public class RequestCtrl {
84 } 88 }
85 } 89 }
86 String where = addJoin.isEmpty() ? "" : " WHERE " + addJoin; 90 String where = addJoin.isEmpty() ? "" : " WHERE " + addJoin;
87 -  
88 - return String.format(QUERY, nbMaxResult, tableName, where); 91 + return String.format(QUERY, nbMaxResult, StringJoiner.join(columnNames), where);
89 } 92 }
90 93
91 /** 94 /**
@@ -132,7 +135,7 @@ public class RequestCtrl { @@ -132,7 +135,7 @@ public class RequestCtrl {
132 135
133 /** 136 /**
134 * Get the parameters. 137 * Get the parameters.
135 - * 138 + *
136 * @return A map of couple <parameter name, parameter value>. 139 * @return A map of couple <parameter name, parameter value>.
137 */ 140 */
138 public Map<String, Object> getParameters() { 141 public Map<String, Object> getParameters() {
src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainpanel/MainPanelCtrl.java
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 16
17 package eu.omp.irap.vespa.epntapclient.gui.mainpanel; 17 package eu.omp.irap.vespa.epntapclient.gui.mainpanel;
18 18
  19 +import java.util.List;
19 import java.util.logging.Level; 20 import java.util.logging.Level;
20 import java.util.logging.Logger; 21 import java.util.logging.Logger;
21 22
@@ -26,11 +27,12 @@ import eu.omp.irap.vespa.epntapclient.gui.requestpanel.RequestPanelCtrl; @@ -26,11 +27,12 @@ import eu.omp.irap.vespa.epntapclient.gui.requestpanel.RequestPanelCtrl;
26 import eu.omp.irap.vespa.epntapclient.gui.resultpanel.ResultPanelCtrl; 27 import eu.omp.irap.vespa.epntapclient.gui.resultpanel.ResultPanelCtrl;
27 import eu.omp.irap.vespa.epntapclient.gui.servicespanel.ServicesPanelCtrl; 28 import eu.omp.irap.vespa.epntapclient.gui.servicespanel.ServicesPanelCtrl;
28 import eu.omp.irap.vespa.votable.controller.VOTableException; 29 import eu.omp.irap.vespa.votable.controller.VOTableException;
  30 +import eu.omp.irap.vespa.votable.utils.StringJoiner;
29 31
30 /** 32 /**
31 * @author N. Jourdane 33 * @author N. Jourdane
32 */ 34 */
33 -public class MainPanelCtrl extends EpnTapController { 35 +public class MainPanelCtrl extends EpnTapController implements MainPanelListener {
34 36
35 /** The logger for the class GUIController. */ 37 /** The logger for the class GUIController. */
36 private static final Logger LOGGER = Logger.getLogger(MainPanelCtrl.class.getName()); 38 private static final Logger LOGGER = Logger.getLogger(MainPanelCtrl.class.getName());
@@ -53,7 +55,7 @@ public class MainPanelCtrl extends EpnTapController { @@ -53,7 +55,7 @@ public class MainPanelCtrl extends EpnTapController {
53 */ 55 */
54 public MainPanelCtrl() { 56 public MainPanelCtrl() {
55 servicesPanelCtrl = new ServicesPanelCtrl(this); 57 servicesPanelCtrl = new ServicesPanelCtrl(this);
56 - resultPanelCtrl = new ResultPanelCtrl(this); 58 + resultPanelCtrl = new ResultPanelCtrl();
57 requestPanelCtrl = new RequestPanelCtrl(this); 59 requestPanelCtrl = new RequestPanelCtrl(this);
58 view = new MainPanelView(this); 60 view = new MainPanelView(this);
59 } 61 }
@@ -74,10 +76,10 @@ public class MainPanelCtrl extends EpnTapController { @@ -74,10 +76,10 @@ public class MainPanelCtrl extends EpnTapController {
74 * @param query The query to send. 76 * @param query The query to send.
75 */ 77 */
76 public void sendQuery(String query) { 78 public void sendQuery(String query) {
77 - String serviceURL = servicesPanelCtrl.getSelectedServiceURL();  
78 - LOGGER.info("Sending query: " + query + " on " + serviceURL); 79 + List<String> selectedServicesUrls = servicesPanelCtrl.getSelectedServicesUrls();
  80 + LOGGER.info("Sending query: " + query + " on " + StringJoiner.join(selectedServicesUrls));
79 try { 81 try {
80 - resultPanelCtrl.updateVOTable(serviceURL, query); 82 + resultPanelCtrl.updateVOTable(StringJoiner.join(selectedServicesUrls), query);
81 view.getResultsPanel().fillTable(resultPanelCtrl.getVOTableData()); 83 view.getResultsPanel().fillTable(resultPanelCtrl.getVOTableData());
82 } catch (VOTableException e) { 84 } catch (VOTableException e) {
83 displayError("Can not send the query.", e); 85 displayError("Can not send the query.", e);
@@ -118,4 +120,29 @@ public class MainPanelCtrl extends EpnTapController { @@ -118,4 +120,29 @@ public class MainPanelCtrl extends EpnTapController {
118 LOGGER.log(Level.SEVERE, message, e); 120 LOGGER.log(Level.SEVERE, message, e);
119 JOptionPane.showMessageDialog(view, e.getMessage(), message, JOptionPane.ERROR_MESSAGE); 121 JOptionPane.showMessageDialog(view, e.getMessage(), message, JOptionPane.ERROR_MESSAGE);
120 } 122 }
  123 +
  124 + @Override
  125 + public void updateQuery() {
  126 + requestPanelCtrl.updateQueryArea();
  127 + }
  128 +
  129 + @Override
  130 + public void sendQuery() {
  131 + List<String> servicesUrls = servicesPanelCtrl.getSelectedServicesUrls();
  132 + List<String> tableNames = servicesPanelCtrl.getSelectedTablesNames();
  133 + try {
  134 + for (int i = 0; i < servicesUrls.size(); i++) {
  135 + String query = requestPanelCtrl.getQuery(tableNames.get(i));
  136 + resultPanelCtrl.updateVOTable(servicesUrls.get(i), query);
  137 + }
  138 + } catch (VOTableException e) {
  139 + displayError("Can not update the VOTable.", e);
  140 + }
  141 + resultPanelCtrl.getView().fillTable(resultPanelCtrl.getVOTableData());
  142 + }
  143 +
  144 + @Override
  145 + public List<String> getTableNames() {
  146 + return servicesPanelCtrl.getSelectedTablesNames();
  147 + }
121 } 148 }
src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainpanel/MainPanelListener.java 0 โ†’ 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +/*
  2 + * This file is a part of EpnTAPClient.
  3 + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer.
  4 + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861
  5 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planรฉtologie.
  6 + *
  7 + * This program is free software: you can
  8 + * redistribute it and/or modify it under the terms of the GNU General Public License as published
  9 + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later
  10 + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY
  11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  12 + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of
  13 + * the GNU General Public License along with this program. If not, see
  14 + * <http://www.gnu.org/licenses/>.
  15 + */
  16 +
  17 +package eu.omp.irap.vespa.epntapclient.gui.mainpanel;
  18 +
  19 +import java.util.List;
  20 +
  21 +/**
  22 + * @author N. Jourdane
  23 + */
  24 +public interface MainPanelListener {
  25 +
  26 + void updateQuery();
  27 +
  28 + void sendQuery();
  29 +
  30 + List<String> getTableNames();
  31 +}
src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/RequestPanelCtrl.java
@@ -16,10 +16,15 @@ @@ -16,10 +16,15 @@
16 16
17 package eu.omp.irap.vespa.epntapclient.gui.requestpanel; 17 package eu.omp.irap.vespa.epntapclient.gui.requestpanel;
18 18
  19 +import java.util.ArrayList;
  20 +import java.util.List;
  21 +import java.util.logging.Level;
19 import java.util.logging.Logger; 22 import java.util.logging.Logger;
20 23
  24 +import javax.swing.JOptionPane;
  25 +
21 import eu.omp.irap.vespa.epntapclient.RequestCtrl; 26 import eu.omp.irap.vespa.epntapclient.RequestCtrl;
22 -import eu.omp.irap.vespa.epntapclient.gui.mainpanel.MainPanelCtrl; 27 +import eu.omp.irap.vespa.epntapclient.gui.mainpanel.MainPanelListener;
23 28
24 /** 29 /**
25 * @author N. Jourdane 30 * @author N. Jourdane
@@ -30,7 +35,7 @@ public class RequestPanelCtrl extends RequestCtrl implements RequestPanelListene @@ -30,7 +35,7 @@ public class RequestPanelCtrl extends RequestCtrl implements RequestPanelListene
30 private static final Logger LOGGER = Logger.getLogger(RequestPanelCtrl.class.getName()); 35 private static final Logger LOGGER = Logger.getLogger(RequestPanelCtrl.class.getName());
31 36
32 /** The controller of the main panel. */ 37 /** The controller of the main panel. */
33 - private MainPanelCtrl mainPanelCtrl; 38 + private MainPanelListener listener;
34 39
35 /** The view of the request panel. */ 40 /** The view of the request panel. */
36 private RequestPanelView view; 41 private RequestPanelView view;
@@ -39,10 +44,10 @@ public class RequestPanelCtrl extends RequestCtrl implements RequestPanelListene @@ -39,10 +44,10 @@ public class RequestPanelCtrl extends RequestCtrl implements RequestPanelListene
39 /** 44 /**
40 * Constructor of RequestPanelCtrl 45 * Constructor of RequestPanelCtrl
41 * 46 *
42 - * @param mainPanelCtrl The controller of the main panel. 47 + * @param listener The listener of the main view.
43 */ 48 */
44 - public RequestPanelCtrl(MainPanelCtrl mainPanelCtrl) {  
45 - this.mainPanelCtrl = mainPanelCtrl; 49 + public RequestPanelCtrl(MainPanelListener listener) {
  50 + this.listener = listener;
46 view = new RequestPanelView(this); 51 view = new RequestPanelView(this);
47 } 52 }
48 53
@@ -53,16 +58,28 @@ public class RequestPanelCtrl extends RequestCtrl implements RequestPanelListene @@ -53,16 +58,28 @@ public class RequestPanelCtrl extends RequestCtrl implements RequestPanelListene
53 return view; 58 return view;
54 } 59 }
55 60
  61 + /**
  62 + * @return The text contained in the query area.
  63 + */
  64 + public String getQuery(String tableName) {
  65 + return view.getQueryArea().getText().replace(TABLE_NAME_KEYWORD, tableName);
  66 + }
  67 +
56 @Override 68 @Override
57 - public void onSendButtonClicked(String query) {  
58 - mainPanelCtrl.sendQuery(query); 69 + public void onSendButtonClicked() {
  70 + listener.sendQuery();
59 } 71 }
60 72
61 /** 73 /**
62 * Update the query area with a working ADQL query, based on the parameters list. 74 * Update the query area with a working ADQL query, based on the parameters list.
63 */ 75 */
64 public void updateQueryArea() { 76 public void updateQueryArea() {
65 - String query = buildQuery(mainPanelCtrl.getServicePanelCtrl().getSelectedTableName()); 77 + // TODO: several services
  78 + // TODO: Add panel to enter column names.
  79 + List<String> columnNames = new ArrayList<>();
  80 + columnNames.add("target_name");
  81 + columnNames.add("target_class");
  82 + String query = buildQuery(columnNames);
66 view.updateQueryArea(query); 83 view.updateQueryArea(query);
67 } 84 }
68 85
@@ -79,4 +96,10 @@ public class RequestPanelCtrl extends RequestCtrl implements RequestPanelListene @@ -79,4 +96,10 @@ public class RequestPanelCtrl extends RequestCtrl implements RequestPanelListene
79 updateQueryArea(); 96 updateQueryArea();
80 LOGGER.info("uploaded " + paramName + ": " + paramValue); 97 LOGGER.info("uploaded " + paramName + ": " + paramValue);
81 } 98 }
  99 +
  100 + @Override
  101 + public void onError(Exception e) {
  102 + LOGGER.log(Level.SEVERE, e.getMessage(), e);
  103 + JOptionPane.showMessageDialog(view, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
  104 + }
82 } 105 }
src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/RequestPanelListener.java
@@ -23,10 +23,8 @@ public interface RequestPanelListener { @@ -23,10 +23,8 @@ public interface RequestPanelListener {
23 23
24 /** 24 /**
25 * Method called when the used click on the 'Send query' button. 25 * Method called when the used click on the 'Send query' button.
26 - *  
27 - * @param query The query  
28 */ 26 */
29 - void onSendButtonClicked(String query); 27 + void onSendButtonClicked();
30 28
31 /** 29 /**
32 * Method called when the user remove a parameter with a parameter field. 30 * Method called when the user remove a parameter with a parameter field.
@@ -43,4 +41,11 @@ public interface RequestPanelListener { @@ -43,4 +41,11 @@ public interface RequestPanelListener {
43 */ 41 */
44 void onParameterChanged(String paramName, Object paramValue); 42 void onParameterChanged(String paramName, Object paramValue);
45 43
  44 + /**
  45 + * Display an error to the user.
  46 + *
  47 + * @param e The error to display to the user.
  48 + */
  49 + public void onError(Exception e);
  50 +
46 } 51 }
src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/RequestPanelView.java
@@ -52,7 +52,7 @@ public class RequestPanelView extends JPanel { @@ -52,7 +52,7 @@ public class RequestPanelView extends JPanel {
52 RequestPanelListener listener; 52 RequestPanelListener listener;
53 53
54 /** The text area where the user write the query. */ 54 /** The text area where the user write the query. */
55 - protected JTextArea queryArea; 55 + private JTextArea queryArea;
56 56
57 /** The parameters fields for the request. */ 57 /** The parameters fields for the request. */
58 private List<ParamField> paramFields; 58 private List<ParamField> paramFields;
@@ -122,7 +122,7 @@ public class RequestPanelView extends JPanel { @@ -122,7 +122,7 @@ public class RequestPanelView extends JPanel {
122 122
123 @Override 123 @Override
124 public void actionPerformed(ActionEvent e) { 124 public void actionPerformed(ActionEvent e) {
125 - listener.onSendButtonClicked(queryArea.getText()); 125 + listener.onSendButtonClicked();
126 } 126 }
127 }); 127 });
128 } 128 }
src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/paramfield/TargetNameField.java
@@ -83,7 +83,7 @@ public class TargetNameField extends ParamField implements TextFieldListener { @@ -83,7 +83,7 @@ public class TargetNameField extends ParamField implements TextFieldListener {
83 this(new RequestPanelListener() { 83 this(new RequestPanelListener() {
84 84
85 @Override 85 @Override
86 - public void onSendButtonClicked(String query) { 86 + public void onSendButtonClicked() {
87 /** No SendButtonClicked event, we just want the field itself. */ 87 /** No SendButtonClicked event, we just want the field itself. */
88 } 88 }
89 89
@@ -96,6 +96,11 @@ public class TargetNameField extends ParamField implements TextFieldListener { @@ -96,6 +96,11 @@ public class TargetNameField extends ParamField implements TextFieldListener {
96 public void onParameterChanged(String paramName, Object paramValue) { 96 public void onParameterChanged(String paramName, Object paramValue) {
97 /** No ParameterChanged event, we just want the field itself. */ 97 /** No ParameterChanged event, we just want the field itself. */
98 } 98 }
  99 +
  100 + @Override
  101 + public void onError(Exception e) {
  102 + /** No Error event, we just want the field itself. */
  103 + }
99 }, paraName); 104 }, paraName);
100 } 105 }
101 106
src/main/java/eu/omp/irap/vespa/epntapclient/gui/resultpanel/ResultPanelCtrl.java
@@ -20,10 +20,15 @@ import java.io.File; @@ -20,10 +20,15 @@ import java.io.File;
20 import java.io.IOException; 20 import java.io.IOException;
21 import java.nio.file.Files; 21 import java.nio.file.Files;
22 import java.nio.file.Paths; 22 import java.nio.file.Paths;
  23 +import java.util.List;
  24 +import java.util.logging.Level;
23 import java.util.logging.Logger; 25 import java.util.logging.Logger;
24 26
25 -import eu.omp.irap.vespa.epntapclient.gui.mainpanel.MainPanelCtrl; 27 +import javax.swing.JOptionPane;
  28 +
26 import eu.omp.irap.vespa.votable.controller.VOTableController; 29 import eu.omp.irap.vespa.votable.controller.VOTableController;
  30 +import eu.omp.irap.vespa.votable.controller.VOTableException.CantSaveVOTableException;
  31 +import eu.omp.irap.vespa.votable.utils.StringJoiner;
27 32
28 /** 33 /**
29 * @author N. Jourdane 34 * @author N. Jourdane
@@ -33,29 +38,23 @@ public class ResultPanelCtrl extends VOTableController implements ResultPanelLis @@ -33,29 +38,23 @@ public class ResultPanelCtrl extends VOTableController implements ResultPanelLis
33 /** The logger for the class ResultPanelCtrl. */ 38 /** The logger for the class ResultPanelCtrl. */
34 private static final Logger LOGGER = Logger.getLogger(ResultPanelCtrl.class.getName()); 39 private static final Logger LOGGER = Logger.getLogger(ResultPanelCtrl.class.getName());
35 40
36 - /** The controller of the main panel. */  
37 - private MainPanelCtrl mainPanelCtrl;  
38 -  
39 /** The result panel view. */ 41 /** The result panel view. */
40 private ResultPanelView view; 42 private ResultPanelView view;
41 43
42 44
43 /** 45 /**
44 * Constructor of ResultPanelCtrl. 46 * Constructor of ResultPanelCtrl.
45 - *  
46 - * @param mainPanelCtrl The controller of the main panel.  
47 */ 47 */
48 - public ResultPanelCtrl(MainPanelCtrl mainPanelCtrl) {  
49 - this.mainPanelCtrl = mainPanelCtrl; 48 + public ResultPanelCtrl() {
50 view = new ResultPanelView(this); 49 view = new ResultPanelView(this);
51 } 50 }
52 51
53 @Override 52 @Override
54 - public void onDownloadButtonClicked(File file) { 53 + public void onDownloadButtonClicked(File file) throws CantSaveVOTableException {
55 try { 54 try {
56 Files.copy(Paths.get(voTablePath), Paths.get(file.getAbsolutePath())); 55 Files.copy(Paths.get(voTablePath), Paths.get(file.getAbsolutePath()));
57 } catch (IOException e) { 56 } catch (IOException e) {
58 - mainPanelCtrl.displayError("Can not save the file.", e); 57 + throw new CantSaveVOTableException(file.getAbsolutePath(), e);
59 } 58 }
60 } 59 }
61 60
@@ -67,7 +66,13 @@ public class ResultPanelCtrl extends VOTableController implements ResultPanelLis @@ -67,7 +66,13 @@ public class ResultPanelCtrl extends VOTableController implements ResultPanelLis
67 } 66 }
68 67
69 @Override 68 @Override
70 - public void onRowSelected(int selectedRow) {  
71 - LOGGER.info("Selected row: " + selectedRow); 69 + public void onRowsSelected(List<Integer> selectedRows) {
  70 + LOGGER.info("Selected row: " + StringJoiner.join(selectedRows));
  71 + }
  72 +
  73 + @Override
  74 + public void onError(Exception e) {
  75 + LOGGER.log(Level.SEVERE, e.getMessage(), e);
  76 + JOptionPane.showMessageDialog(view, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
72 } 77 }
73 } 78 }
src/main/java/eu/omp/irap/vespa/epntapclient/gui/resultpanel/ResultPanelListener.java
@@ -18,6 +18,7 @@ package eu.omp.irap.vespa.epntapclient.gui.resultpanel; @@ -18,6 +18,7 @@ package eu.omp.irap.vespa.epntapclient.gui.resultpanel;
18 18
19 import java.io.File; 19 import java.io.File;
20 20
  21 +import eu.omp.irap.vespa.votable.controller.VOTableException.CantSaveVOTableException;
21 import eu.omp.irap.vespa.votable.view.VOTableViewListener; 22 import eu.omp.irap.vespa.votable.view.VOTableViewListener;
22 23
23 /** 24 /**
@@ -26,10 +27,18 @@ import eu.omp.irap.vespa.votable.view.VOTableViewListener; @@ -26,10 +27,18 @@ import eu.omp.irap.vespa.votable.view.VOTableViewListener;
26 public interface ResultPanelListener extends VOTableViewListener { 27 public interface ResultPanelListener extends VOTableViewListener {
27 28
28 /** 29 /**
29 - * Copy the VOTable to a specified location. 30 + * This method is called when the user clicks on the download button.
30 * 31 *
31 * @param file The file selected by the user in the FileChooser pop-up, corresponding to the 32 * @param file The file selected by the user in the FileChooser pop-up, corresponding to the
32 * place where save the VOTable. 33 * place where save the VOTable.
  34 + * @throws CantSaveVOTableException The VOTable can not be saved at the specified location.
33 */ 35 */
34 - public void onDownloadButtonClicked(File file); 36 + public void onDownloadButtonClicked(File file) throws CantSaveVOTableException;
  37 +
  38 + /**
  39 + * Display an error to the user.
  40 + *
  41 + * @param e The error to display to the user.
  42 + */
  43 + public void onError(Exception e);
35 } 44 }
src/main/java/eu/omp/irap/vespa/epntapclient/gui/resultpanel/ResultPanelView.java
@@ -25,6 +25,7 @@ import javax.swing.JFileChooser; @@ -25,6 +25,7 @@ import javax.swing.JFileChooser;
25 import javax.swing.JLabel; 25 import javax.swing.JLabel;
26 import javax.swing.JPanel; 26 import javax.swing.JPanel;
27 27
  28 +import eu.omp.irap.vespa.votable.controller.VOTableException.CantSaveVOTableException;
28 import eu.omp.irap.vespa.votable.view.VOTableView; 29 import eu.omp.irap.vespa.votable.view.VOTableView;
29 30
30 /** 31 /**
@@ -96,10 +97,14 @@ public class ResultPanelView extends VOTableView { @@ -96,10 +97,14 @@ public class ResultPanelView extends VOTableView {
96 fileButton.addActionListener(new ActionListener() { 97 fileButton.addActionListener(new ActionListener() {
97 98
98 @Override 99 @Override
99 - public void actionPerformed(ActionEvent e) { 100 + public void actionPerformed(ActionEvent evt) {
100 final JFileChooser fc = new JFileChooser(); 101 final JFileChooser fc = new JFileChooser();
101 fc.showOpenDialog(ResultPanelView.this); 102 fc.showOpenDialog(ResultPanelView.this);
102 - listener.onDownloadButtonClicked(fc.getSelectedFile()); 103 + try {
  104 + listener.onDownloadButtonClicked(fc.getSelectedFile());
  105 + } catch (CantSaveVOTableException e) {
  106 + listener.onError(e);
  107 + }
103 } 108 }
104 }); 109 });
105 } 110 }
src/main/java/eu/omp/irap/vespa/epntapclient/gui/servicespanel/ServicesPanelCtrl.java
@@ -16,13 +16,16 @@ @@ -16,13 +16,16 @@
16 16
17 package eu.omp.irap.vespa.epntapclient.gui.servicespanel; 17 package eu.omp.irap.vespa.epntapclient.gui.servicespanel;
18 18
  19 +import java.util.ArrayList;
  20 +import java.util.List;
19 import java.util.logging.Logger; 21 import java.util.logging.Logger;
20 22
21 -import eu.omp.irap.vespa.epntapclient.gui.mainpanel.MainPanelCtrl; 23 +import eu.omp.irap.vespa.epntapclient.gui.mainpanel.MainPanelListener;
22 import eu.omp.irap.vespa.epntapclient.service.Queries; 24 import eu.omp.irap.vespa.epntapclient.service.Queries;
23 import eu.omp.irap.vespa.epntapclient.service.ServiceCore; 25 import eu.omp.irap.vespa.epntapclient.service.ServiceCore;
24 import eu.omp.irap.vespa.votable.Consts; 26 import eu.omp.irap.vespa.votable.Consts;
25 import eu.omp.irap.vespa.votable.controller.VOTableController; 27 import eu.omp.irap.vespa.votable.controller.VOTableController;
  28 +import eu.omp.irap.vespa.votable.utils.StringJoiner;
26 29
27 /** 30 /**
28 * @author N. Jourdane 31 * @author N. Jourdane
@@ -32,26 +35,32 @@ public class ServicesPanelCtrl extends VOTableController implements ServicesPane @@ -32,26 +35,32 @@ public class ServicesPanelCtrl extends VOTableController implements ServicesPane
32 /** The logger for the class ServicesPanelCtrl. */ 35 /** The logger for the class ServicesPanelCtrl. */
33 private static final Logger LOGGER = Logger.getLogger(ServicesPanelCtrl.class.getName()); 36 private static final Logger LOGGER = Logger.getLogger(ServicesPanelCtrl.class.getName());
34 37
35 - /** The controller of the main panel. */  
36 - private MainPanelCtrl mainPanelCtrl; 38 + /** The position of the column displaying the table names in the service table. */
  39 + private static final int TABLE_NAME_COLUMN_POSITION = 4;
  40 +
  41 + /** The position of the column displaying the services target URLs in the service table. */
  42 + private static final int SERVICE_URL_COLUMN_POSITION = 1;
37 43
38 /** The view of the services panel. */ 44 /** The view of the services panel. */
39 private ServicesPanelView view; 45 private ServicesPanelView view;
40 46
41 - /** The name of the table selected by the user on the table list panel. */  
42 - private String selectedTableName; 47 + /** The list of services table names selected by the user on the service panel. */
  48 + private List<String> selectedTablesNames;
  49 +
  50 + /** The list of services target Urls selected by the user on the service panel. */
  51 + private List<String> selectedServicesUrls;
43 52
44 - /** The URL of the service corresponding to the selected table. */  
45 - private String selectedServiceURL; 53 + /** The listener of the main panel. */
  54 + private MainPanelListener listener;
46 55
47 56
48 /** 57 /**
49 * Constructor of ServicesPanelCtrl 58 * Constructor of ServicesPanelCtrl
50 * 59 *
51 - * @param mainPanelCtrl The controller of the main panel. 60 + * @param listener The listener of the main panel.
52 */ 61 */
53 - public ServicesPanelCtrl(MainPanelCtrl mainPanelCtrl) {  
54 - this.mainPanelCtrl = mainPanelCtrl; 62 + public ServicesPanelCtrl(MainPanelListener listener) {
  63 + this.listener = listener;
55 targetURL = Consts.DEFAULT_REGISTRY_URL; 64 targetURL = Consts.DEFAULT_REGISTRY_URL;
56 query = String.format(Queries.SELECT_ALL_TAP_SERVICES_WHERE_CORE, ServiceCore.EPNCORE); 65 query = String.format(Queries.SELECT_ALL_TAP_SERVICES_WHERE_CORE, ServiceCore.EPNCORE);
57 view = new ServicesPanelView(this); 66 view = new ServicesPanelView(this);
@@ -65,30 +74,41 @@ public class ServicesPanelCtrl extends VOTableController implements ServicesPane @@ -65,30 +74,41 @@ public class ServicesPanelCtrl extends VOTableController implements ServicesPane
65 } 74 }
66 75
67 /** 76 /**
68 - * @return The table name of the service selected by the user on the services table list. 77 + * @return The list of services table names selected by the user on the service panel.
69 */ 78 */
70 - public String getSelectedTableName() {  
71 - return selectedTableName; 79 + public List<String> getSelectedTablesNames() {
  80 + return selectedTablesNames;
72 } 81 }
73 82
74 /** 83 /**
75 - * @return The access URL of the service selected by the user on the services table list. 84 + * @return The list of services target Urls selected by the user on the service panel.
76 */ 85 */
77 - public String getSelectedServiceURL() {  
78 - return selectedServiceURL; 86 + public List<String> getSelectedServicesUrls() {
  87 + return selectedServicesUrls;
79 } 88 }
80 89
81 @Override 90 @Override
82 - public void onRowSelected(int selectedServiceRow) {  
83 - String serviceURL = view.getServiceURL(selectedServiceRow);  
84 - String tableName = view.getTableName(selectedServiceRow);  
85 - if (!tableName.equals(selectedTableName)) {  
86 - selectedServiceURL = serviceURL;  
87 - selectedTableName = tableName;  
88 - mainPanelCtrl.getRequestPanelCtrl().updateQueryArea();  
89 - LOGGER.info(  
90 - "Selected table: " + selectedTableName + " - service: " + selectedServiceURL); 91 + public void onRowsSelected(List<Integer> selectedRows) {
  92 + List<String> servicesUrls = new ArrayList<>();
  93 + List<String> tableNames = new ArrayList<>();
  94 + String customServiceUrl = view.getServiceUrlTextField().getText();
  95 + String customTableName = view.getTableNameTextField().getText();
  96 +
  97 + for (int row : selectedRows) {
  98 + servicesUrls.add((String) view.getValueAt(SERVICE_URL_COLUMN_POSITION, row));
  99 + tableNames.add((String) view.getValueAt(TABLE_NAME_COLUMN_POSITION, row));
  100 + }
  101 + if (!customServiceUrl.isEmpty() && !customTableName.isEmpty()) {
  102 + servicesUrls.add(customServiceUrl);
  103 + tableNames.add(customTableName);
91 } 104 }
  105 +
  106 + selectedServicesUrls = servicesUrls;
  107 + selectedTablesNames = tableNames;
  108 + LOGGER.info("Selected services URLs: " + StringJoiner.join(selectedServicesUrls));
  109 + LOGGER.info("Selected tables names: " + StringJoiner.join(selectedTablesNames));
  110 +
  111 + listener.updateQuery();
92 } 112 }
93 113
94 } 114 }
src/main/java/eu/omp/irap/vespa/epntapclient/gui/servicespanel/ServicesPanelListener.java
@@ -22,5 +22,5 @@ import eu.omp.irap.vespa.votable.view.VOTableViewListener; @@ -22,5 +22,5 @@ import eu.omp.irap.vespa.votable.view.VOTableViewListener;
22 * @author N. Jourdane 22 * @author N. Jourdane
23 */ 23 */
24 public interface ServicesPanelListener extends VOTableViewListener { 24 public interface ServicesPanelListener extends VOTableViewListener {
25 - /* Nothing to listen yet except service selection, listened by VOTableViewListener. */ 25 +
26 } 26 }
src/main/java/eu/omp/irap/vespa/epntapclient/gui/servicespanel/ServicesPanelView.java
@@ -32,12 +32,6 @@ import eu.omp.irap.vespa.votable.view.VOTableView; @@ -32,12 +32,6 @@ import eu.omp.irap.vespa.votable.view.VOTableView;
32 */ 32 */
33 public class ServicesPanelView extends VOTableView { 33 public class ServicesPanelView extends VOTableView {
34 34
35 - /** */  
36 - private static final int TABLE_NAME_COLUMN_POSITION = 4;  
37 -  
38 - /** */  
39 - private static final int SERVICE_URL_COLUMN_POSITION = 1;  
40 -  
41 /** The serial version UID. */ 35 /** The serial version UID. */
42 private static final long serialVersionUID = 1L; 36 private static final long serialVersionUID = 1L;
43 37
@@ -86,7 +80,7 @@ public class ServicesPanelView extends VOTableView { @@ -86,7 +80,7 @@ public class ServicesPanelView extends VOTableView {
86 * 80 *
87 * @return The table name JTextField. 81 * @return The table name JTextField.
88 */ 82 */
89 - private JTextField getTableNameTextField() { 83 + public JTextField getTableNameTextField() {
90 return tableNameTextField == null ? new JTextField(10) : tableNameTextField; 84 return tableNameTextField == null ? new JTextField(10) : tableNameTextField;
91 } 85 }
92 86
@@ -95,7 +89,7 @@ public class ServicesPanelView extends VOTableView { @@ -95,7 +89,7 @@ public class ServicesPanelView extends VOTableView {
95 * 89 *
96 * @return The service URL JTextField. 90 * @return The service URL JTextField.
97 */ 91 */
98 - private JTextField getServiceUrlTextField() { 92 + public JTextField getServiceUrlTextField() {
99 return serviceUrlTextField == null ? new JTextField(10) : serviceUrlTextField; 93 return serviceUrlTextField == null ? new JTextField(10) : serviceUrlTextField;
100 } 94 }
101 95
@@ -113,32 +107,11 @@ public class ServicesPanelView extends VOTableView { @@ -113,32 +107,11 @@ public class ServicesPanelView extends VOTableView {
113 107
114 @Override 108 @Override
115 public void actionPerformed(ActionEvent e) { 109 public void actionPerformed(ActionEvent e) {
116 - listener.onRowSelected(-1); 110 + listener.onRowsSelected(null);
117 } 111 }
118 }); 112 });
119 } 113 }
120 return serviceButton; 114 return serviceButton;
121 } 115 }
122 116
123 - /**  
124 - * @param row The row index in the JTable element.  
125 - * @return The URL of the service corresponding to the row.  
126 - */  
127 - public String getServiceURL(int row) {  
128 - if (row == -1) {  
129 - return serviceUrlTextField.getText();  
130 - }  
131 - return (String) getValueAt(SERVICE_URL_COLUMN_POSITION, row);  
132 - }  
133 -  
134 - /**  
135 - * @param row The row index in the JTable element.  
136 - * @return The table name of the service corresponding to the row.  
137 - */  
138 - public String getTableName(int row) {  
139 - if (row == -1) {  
140 - return tableNameTextField.getText();  
141 - }  
142 - return (String) getValueAt(TABLE_NAME_COLUMN_POSITION, row);  
143 - }  
144 } 117 }