Blame view

src/main/java/eu/omp/irap/vespa/epntapclient/view/ParamField.java 21.9 KB
506d0c0b   Nathanael Jourdane   Add licence heade...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 * This file is a part of EpnTAPClient.
 * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer.
 * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861
 * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie.
 * 
 * This program is free software: you can
 * redistribute it and/or modify it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or (at your option) any later
 * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU General Public License for more details. You should have received a copy of
 * the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */

eb483599   Nathanael Jourdane   Add missing Param...
17
18
19
20
package eu.omp.irap.vespa.epntapclient.view;

import java.awt.Color;
import java.awt.Dimension;
a99d92fa   Nathanael Jourdane   Add JComboBox for...
21
22
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
eb483599   Nathanael Jourdane   Add missing Param...
23
24
25
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
e7647bba   Nathanael Jourdane   change query to g...
26
import java.util.ArrayList;
e7647bba   Nathanael Jourdane   change query to g...
27
import java.util.List;
eb483599   Nathanael Jourdane   Add missing Param...
28
import java.util.Locale;
b6627be6   Nathanael Jourdane   Improve Exceptions
29
import java.util.logging.Level;
5d3c344e   Nathanael Jourdane   Use Java logging ...
30
import java.util.logging.Logger;
eb483599   Nathanael Jourdane   Add missing Param...
31
32

import javax.swing.BoxLayout;
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
33
import javax.swing.JComboBox;
eb483599   Nathanael Jourdane   Add missing Param...
34
35
36
37
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
eb483599   Nathanael Jourdane   Add missing Param...
38
39
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
eb483599   Nathanael Jourdane   Add missing Param...
40

05b140ed   Nathanael Jourdane   TargetNameField J...
41
42
43
44
45
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableConnection;
d3a65e87   Nathanael Jourdane   Improve Javadoc.
46
import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.CantSendQueryException;
05b140ed   Nathanael Jourdane   TargetNameField J...
47

a227a22d   Nathanael Jourdane   Add comments.
48
/**
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
49
50
51
52
 * A field used to set a service parameter to build the query (in the parameter panel). ParamField
 * is an abstract method and all type of parameter field should extend it. See
 * https://voparis-confluence.obspm.fr/display/VES/4+-+EPN-TAP+queries to get all parameters
 * details.
a227a22d   Nathanael Jourdane   Add comments.
53
54
55
 * 
 * @author N. Jourdane
 */
eb483599   Nathanael Jourdane   Add missing Param...
56
public abstract class ParamField extends JPanel {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
57
	/** The serial version UID (affected with a random number). */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
58
59
	private static final long serialVersionUID = 6025994164004985362L;

5d3c344e   Nathanael Jourdane   Use Java logging ...
60
	/** The logger for the class ParamField. */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
61
	static final Logger logger = Logger.getLogger(ParamField.class.getName());
eb483599   Nathanael Jourdane   Add missing Param...
62

a227a22d   Nathanael Jourdane   Add comments.
63
	/** The minimum width of the field. */
68ae1315   Nathanael Jourdane   Improve GUI appar...
64
	private static final int MIN_FIELD_WIDTH = 30;
a227a22d   Nathanael Jourdane   Add comments.
65
	/** The preferred field height. */
68ae1315   Nathanael Jourdane   Improve GUI appar...
66
	private static final int FIELD_HEIGHT = 20;
a227a22d   Nathanael Jourdane   Add comments.
67
	/** The maximum width of the field. */
68ae1315   Nathanael Jourdane   Improve GUI appar...
68
	private static final int MAX_FIELD_WIDTH = 400;
a227a22d   Nathanael Jourdane   Add comments.
69
	/** The preferred label width. */
68ae1315   Nathanael Jourdane   Improve GUI appar...
70
71
	private static final int LABEL_WIDTH = 140;

a227a22d   Nathanael Jourdane   Add comments.
72
	/** The URL of the resolver used for the `target name` field. */
05b140ed   Nathanael Jourdane   TargetNameField J...
73
	private static final String RESOLVER_URL = "http://voparis-registry.obspm.fr/ssodnet/1/autocomplete";
a227a22d   Nathanael Jourdane   Add comments.
74
	/** The date format used in the DateRange field */
eb483599   Nathanael Jourdane   Add missing Param...
75
	private static final String DATE_FORMAT = "dd/MM/yyyy";
a227a22d   Nathanael Jourdane   Add comments.
76
	/** The regex used to validate the Date fields */
eb483599   Nathanael Jourdane   Add missing Param...
77
	private static final String DATE_REGEX = "(^(((0[1-9]|1[0-9]|2[0-8])[\\/](0[1-9]|1[012]))|((29|30|31)[\\/](0[13578]|1[02]))|((29|30)[\\/](0[4,6,9]|11)))[\\/](19|[2-9][0-9])\\d\\d$)|(^29[\\/]02[\\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)";
a227a22d   Nathanael Jourdane   Add comments.
78
	/** The suffix used in REG-TAP parameters names, indicating that it's a beginning of a range. */
eb483599   Nathanael Jourdane   Add missing Param...
79
	private static final String MIN_SUFFIX = "min";
a227a22d   Nathanael Jourdane   Add comments.
80
	/** The suffix used in REG-TAP parameters names, indicating that it is a end of a range. */
eb483599   Nathanael Jourdane   Add missing Param...
81
82
	private static final String MAX_SUFFIX = "max";

a227a22d   Nathanael Jourdane   Add comments.
83
	/** The main view of the application. */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
84
	protected EpnTapMainView mainView;
a227a22d   Nathanael Jourdane   Add comments.
85
	/** The parameter name of the field */
eb483599   Nathanael Jourdane   Add missing Param...
86
87
	protected String paramName;

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
88
89
90
91
92
93
94
	/**
	 * Method constructor for the parameter field abstract class, which do all common action for all
	 * type of field, such as displaying the name of the parameter.
	 * 
	 * @param mainView The main view of the application.
	 * @param paramName The name of the parameter.
	 */
5af53be7   Nathanael Jourdane   Make the applicat...
95
	public ParamField(EpnTapMainView mainView, String paramName) {
eb483599   Nathanael Jourdane   Add missing Param...
96
		super();
5af53be7   Nathanael Jourdane   Make the applicat...
97
98
99
100

		this.mainView = mainView;
		this.paramName = paramName;

eb483599   Nathanael Jourdane   Add missing Param...
101
		this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
68ae1315   Nathanael Jourdane   Improve GUI appar...
102
		this.setMaximumSize(new Dimension(MAX_FIELD_WIDTH, FIELD_HEIGHT));
eb483599   Nathanael Jourdane   Add missing Param...
103
104
		String strLabel = paramName.replaceAll("_", " ").trim();
		JLabel label = new JLabel(strLabel.substring(0, 1).toUpperCase() + strLabel.substring(1));
68ae1315   Nathanael Jourdane   Improve GUI appar...
105
		label.setPreferredSize(new Dimension(LABEL_WIDTH, FIELD_HEIGHT));
eb483599   Nathanael Jourdane   Add missing Param...
106
		this.add(label);
41133475   Nathanael Jourdane   build floatRangeF...
107
		// TODO: Add tooltip text based on rr.table_column.column_description
eb483599   Nathanael Jourdane   Add missing Param...
108
109
	}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
110
111
112
113
114
115
	/**
	 * The string field is used for parameter with a `String` class. It is a simple JTextField with
	 * no verification. The parameter is sent to the controller each time it is modified.
	 * 
	 * @author N. Jourdane
	 */
e97b40e8   Nathanael Jourdane   Make ParamField c...
116
	public static class StringField extends ParamField implements TextFieldListener {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
117
		/** The serial version UID (affected with a random number). */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
118
		private static final long serialVersionUID = 24219488975302068L;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
119
		/** The JTextField used to put the parameter value. */
667dd80c   Nathanael Jourdane   JTextField as Par...
120
121
		JTextField field;

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
122
123
124
125
126
127
		/**
		 * Method constructor for the string field.
		 * 
		 * @param mainView The main view of the application.
		 * @param paramName The name of the parameter.
		 */
5af53be7   Nathanael Jourdane   Make the applicat...
128
129
		public StringField(EpnTapMainView mainView, String paramName) {
			super(mainView, paramName);
667dd80c   Nathanael Jourdane   JTextField as Par...
130
			field = new JTextField();
e97b40e8   Nathanael Jourdane   Make ParamField c...
131
			addChangeListener(this, field);
eb483599   Nathanael Jourdane   Add missing Param...
132
133
134
			this.add(field);
		}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
135
136
137
		/**
		 * This method is called each time the field is modified.
		 */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
138
139
140
		@Override
		public void update(JTextField textField) {
			if ("".equals(textField.getText())) {
4268557f   Nathanael Jourdane   Fix some Sonar is...
141
				mainView.event(Event.PARAMETER_CHANGED, paramName, null);
eb483599   Nathanael Jourdane   Add missing Param...
142
			} else {
4268557f   Nathanael Jourdane   Fix some Sonar is...
143
				mainView.event(Event.PARAMETER_CHANGED, paramName, textField.getText());
eb483599   Nathanael Jourdane   Add missing Param...
144
145
146
147
			}
		}
	}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
148
149
150
151
152
153
154
	/**
	 * The float field is used for parameter with a `Float` class. It is a JTextField which checks
	 * if the content is a valid float. If the parameter is valid or if it is empty, then the float
	 * value is sent to the controller.
	 * 
	 * @author N. Jourdane
	 */
e97b40e8   Nathanael Jourdane   Make ParamField c...
155
	public static class FloatField extends ParamField implements TextFieldListener {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
156
		/** The serial version UID (affected with a random number). */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
157
		private static final long serialVersionUID = -1880193152285564590L;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
158
		/** The JTextField used to put the parameter value. */
667dd80c   Nathanael Jourdane   JTextField as Par...
159
160
		JTextField field;

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
161
162
163
164
165
166
		/**
		 * Method constructor
		 * 
		 * @param mainView The main view of the application.
		 * @param paramName The name of the parameter.
		 */
5af53be7   Nathanael Jourdane   Make the applicat...
167
168
		public FloatField(EpnTapMainView mainView, String paramName) {
			super(mainView, paramName);
667dd80c   Nathanael Jourdane   JTextField as Par...
169
			field = new JTextField();
e97b40e8   Nathanael Jourdane   Make ParamField c...
170
			addChangeListener(this, field);
eb483599   Nathanael Jourdane   Add missing Param...
171
172
173
			this.add(field);
		}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
174
175
176
		/**
		 * This method is called each time the field is modified.
		 */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
177
178
179
180
		@Override
		public void update(JTextField textField) {
			if ("".equals(textField.getText())) {
				textField.setBackground(Color.WHITE);
4268557f   Nathanael Jourdane   Fix some Sonar is...
181
				mainView.event(Event.PARAMETER_REMOVED, paramName);
eb483599   Nathanael Jourdane   Add missing Param...
182
183
			} else {
				try {
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
184
					float value = Float.parseFloat(textField.getText());
4268557f   Nathanael Jourdane   Fix some Sonar is...
185
					mainView.event(Event.PARAMETER_CHANGED, paramName, value);
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
186
187
188
					textField.setBackground(Color.WHITE);
				} catch (@SuppressWarnings("unused") NumberFormatException e) {
					textField.setBackground(Color.PINK);
eb483599   Nathanael Jourdane   Add missing Param...
189
190
191
192
193
				}
			}
		}
	}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
194
195
196
197
198
199
200
201
	/**
	 * The date range field is used for couples of parameter with both a `Date` type (actually only
	 * `time_min` and `time_max` parameters is concerned for now). These are JTextFields which check
	 * if the content is a valid date, according to DATE_FORMAT. If the parameter is valid or if it
	 * is empty, then the dates value are sent to the controller, in Julian Day format.
	 * 
	 * @author N. Jourdane
	 */
e97b40e8   Nathanael Jourdane   Make ParamField c...
202
	public static class DateRangeField extends ParamField implements TextFieldListener {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
203
		/** The serial version UID (affected with a random number). */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
204
		private static final long serialVersionUID = -7781309003911514777L;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
205
		/** The JTextField used to put the parameter minimum value of the range. */
667dd80c   Nathanael Jourdane   JTextField as Par...
206
		JTextField fieldMin;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
207
		/** The JTextField used to put the parameter maximum value of the range. */
667dd80c   Nathanael Jourdane   JTextField as Par...
208
209
		JTextField fieldMax;

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
210
211
212
213
214
215
		/**
		 * Method constructor
		 * 
		 * @param mainView The main view of the application.
		 * @param paramName The name of the parameter.
		 */
5af53be7   Nathanael Jourdane   Make the applicat...
216
217
		public DateRangeField(EpnTapMainView mainView, String paramName) {
			super(mainView, paramName);
68ae1315   Nathanael Jourdane   Improve GUI appar...
218
			this.add(new JLabel("min "));
667dd80c   Nathanael Jourdane   JTextField as Par...
219
			fieldMin = new JTextField();
e97b40e8   Nathanael Jourdane   Make ParamField c...
220
			fieldMin.setName(MIN_SUFFIX);
68ae1315   Nathanael Jourdane   Improve GUI appar...
221
			fieldMin.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));
e97b40e8   Nathanael Jourdane   Make ParamField c...
222
			addChangeListener(this, fieldMin);
eb483599   Nathanael Jourdane   Add missing Param...
223
224
			this.add(fieldMin);

68ae1315   Nathanael Jourdane   Improve GUI appar...
225
			this.add(new JLabel("max "));
667dd80c   Nathanael Jourdane   JTextField as Par...
226
			fieldMax = new JTextField();
e97b40e8   Nathanael Jourdane   Make ParamField c...
227
			fieldMax.setName(MAX_SUFFIX);
68ae1315   Nathanael Jourdane   Improve GUI appar...
228
			fieldMax.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));
e97b40e8   Nathanael Jourdane   Make ParamField c...
229
			addChangeListener(this, fieldMin);
eb483599   Nathanael Jourdane   Add missing Param...
230
231
232
			this.add(fieldMax);
		}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
233
234
235
		/**
		 * This method is called each time the field is modified.
		 */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
236
		@Override
e97b40e8   Nathanael Jourdane   Make ParamField c...
237
		public void update(JTextField field) {
eb483599   Nathanael Jourdane   Add missing Param...
238
239
240
			DateFormat df = new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH);
			if ("".equals(field.getText())) {
				field.setBackground(Color.WHITE);
4268557f   Nathanael Jourdane   Fix some Sonar is...
241
				mainView.event(Event.PARAMETER_REMOVED, paramName + field.getName());
eb483599   Nathanael Jourdane   Add missing Param...
242
243
244
			} else if (field.getText().matches(DATE_REGEX)) {
				try {
					long date = df.parse(field.getText()).getTime();
5af53be7   Nathanael Jourdane   Make the applicat...
245
					date = Math.round((date / 86400000.0) + 2440587.5); // to JD
4268557f   Nathanael Jourdane   Fix some Sonar is...
246
					mainView.event(Event.PARAMETER_CHANGED, paramName + field.getName(), date);
eb483599   Nathanael Jourdane   Add missing Param...
247
					field.setBackground(Color.WHITE);
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
248
				} catch (@SuppressWarnings("unused") ParseException e) {
eb483599   Nathanael Jourdane   Add missing Param...
249
250
251
252
253
254
255
256
257
					field.setBackground(Color.PINK);
				}
				// TODO: check if date min < date max
			} else {
				field.setBackground(Color.PINK);
			}
		}
	}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
258
259
260
261
262
263
264
	/**
	 * The float range field is used for couples of parameter with both a `Float` class. These are
	 * JTextFields which check if the content is a valid float. If the parameter is valid or if it
	 * is empty, then the float value are sent to the controller.
	 * 
	 * @author N. Jourdane
	 */
e97b40e8   Nathanael Jourdane   Make ParamField c...
265
	public static class FloatRangeField extends ParamField implements TextFieldListener {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
266
		/** The serial version UID (affected with a random number). */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
267
		private static final long serialVersionUID = 7923358142882329015L;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
268
		/** The JTextField used to put the parameter minimum value of the range. */
41133475   Nathanael Jourdane   build floatRangeF...
269
		JTextField fieldMin;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
270
		/** The JTextField used to put the parameter maximum value of the range. */
41133475   Nathanael Jourdane   build floatRangeF...
271
		JTextField fieldMax;
eb483599   Nathanael Jourdane   Add missing Param...
272

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
273
274
275
276
277
278
		/**
		 * Method constructor
		 * 
		 * @param mainView The main view of the application.
		 * @param paramName The name of the parameter.
		 */
5af53be7   Nathanael Jourdane   Make the applicat...
279
280
		public FloatRangeField(EpnTapMainView mainView, String paramName) {
			super(mainView, paramName);
41133475   Nathanael Jourdane   build floatRangeF...
281
			fieldMin = new JTextField();
e97b40e8   Nathanael Jourdane   Make ParamField c...
282
283
			fieldMin.setName(MIN_SUFFIX);
			addChangeListener(this, fieldMin);
eb483599   Nathanael Jourdane   Add missing Param...
284
285
			this.add(fieldMin);

41133475   Nathanael Jourdane   build floatRangeF...
286
			fieldMax = new JTextField();
e97b40e8   Nathanael Jourdane   Make ParamField c...
287
288
			fieldMax.setName(MAX_SUFFIX);
			addChangeListener(this, fieldMax);
eb483599   Nathanael Jourdane   Add missing Param...
289
290
			this.add(fieldMax);
		}
41133475   Nathanael Jourdane   build floatRangeF...
291

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
292
293
294
		/**
		 * This method is called each time the field is modified.
		 */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
295
		@Override
e97b40e8   Nathanael Jourdane   Make ParamField c...
296
		public void update(JTextField field) {
41133475   Nathanael Jourdane   build floatRangeF...
297
298
			if ("".equals(field.getText())) {
				field.setBackground(Color.WHITE);
4268557f   Nathanael Jourdane   Fix some Sonar is...
299
				mainView.event(Event.PARAMETER_REMOVED, paramName + field.getName());
41133475   Nathanael Jourdane   build floatRangeF...
300
301
			} else {
				try {
4268557f   Nathanael Jourdane   Fix some Sonar is...
302
					mainView.event(Event.PARAMETER_CHANGED, paramName + field.getName(),
e97b40e8   Nathanael Jourdane   Make ParamField c...
303
							Float.parseFloat(field.getText()));
41133475   Nathanael Jourdane   build floatRangeF...
304
					field.setBackground(Color.WHITE);
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
305
				} catch (@SuppressWarnings("unused") NumberFormatException e) {
41133475   Nathanael Jourdane   build floatRangeF...
306
307
308
309
					field.setBackground(Color.PINK);
				}
			}
		}
eb483599   Nathanael Jourdane   Add missing Param...
310
311
	}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
312
313
314
315
316
317
318
319
	/**
	 * The target name field is used only for the `target_name` parameter. It is a ComboBox which is
	 * automatically filled with actual target names which begins by the entered characters, by
	 * asking to an online resolver (RESOLVER_URL). The parameter is sent to the controller each
	 * time it is updated, so it is possible to enter a parameter that the resolver do not know.
	 * 
	 * @author N. Jourdane
	 */
e97b40e8   Nathanael Jourdane   Make ParamField c...
320
	public static class TargetNameField extends ParamField implements TextFieldListener {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
321
		/** The serial version UID (affected with a random number). */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
322
		private static final long serialVersionUID = 5136431108894677113L;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
323
		/** The comboBox to enter the target_name and display target name propositions. */
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
324
		JComboBox<String> comboBox;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
325
		/** The JTextField related to the ComboBox, allowing to listen for text content update. */
667dd80c   Nathanael Jourdane   JTextField as Par...
326
		JTextField field;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
327
328
329
330
331
		/**
		 * The content of the last entered value. It is used to avoid recursions, because each time
		 * an update event is detected, the resolver is called and the ComboBox is filled with new
		 * values, which trigger a new event.
		 */
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
332
		String lastContent;
667dd80c   Nathanael Jourdane   JTextField as Par...
333

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
334
		/**
4268557f   Nathanael Jourdane   Fix some Sonar is...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
		 * This method is called each time the field is modified. A Runnable is used it is
		 * impossible to modify the comboBox from a DocumentEvent.
		 */
		Runnable updateComboBox = new Runnable() {
			@Override
			public void run() {
				String content = field.getText();
				if (!content.equals(lastContent)) {
					if (content.length() >= 2) {
						lastContent = content;
						comboBox.removeAllItems();
						try {
							for (String s : getItems(content)) {
								comboBox.addItem(s);
							}
						} catch (CantSendQueryException e) {
							logger.log(Level.WARNING, "Can't get table names for the resolver", e);
						}
						comboBox.getEditor().setItem(content);
					}
					if ("".equals(content)) {
						mainView.event(Event.PARAMETER_REMOVED, paramName);
					} else {
						mainView.event(Event.PARAMETER_CHANGED, paramName, content);
					}
				}
			}
		};

		/**
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
365
366
367
368
369
		 * Method constructor
		 * 
		 * @param mainView The main view of the application.
		 * @param paramName The name of the parameter.
		 */
5af53be7   Nathanael Jourdane   Make the applicat...
370
371
		public TargetNameField(EpnTapMainView mainView, String paramName) {
			super(mainView, paramName);
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
372
			comboBox = new JComboBox<>();
68ae1315   Nathanael Jourdane   Improve GUI appar...
373
374
			comboBox.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));

f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
375
376
			comboBox.setEditable(true);
			field = (JTextField) comboBox.getEditor().getEditorComponent();
e97b40e8   Nathanael Jourdane   Make ParamField c...
377
			addChangeListener(this, field);
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
378
379
380
			this.add(comboBox);
		}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
381
382
383
384
385
		/**
		 * The method used to get target names propositions by asking to the resolver.
		 * 
		 * @param begining The beginning of the target_name.
		 * @return An array of Strings corresponding to the target names got.
d3a65e87   Nathanael Jourdane   Improve Javadoc.
386
		 * @throws CantSendQueryException If the resolver do not work.
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
387
		 */
d3a65e87   Nathanael Jourdane   Improve Javadoc.
388
		static String[] getItems(String begining) throws CantSendQueryException {
4268557f   Nathanael Jourdane   Fix some Sonar is...
389
			StringBuilder resolverResult;
b6627be6   Nathanael Jourdane   Improve Exceptions
390
			resolverResult = VOTableConnection.sendGet(RESOLVER_URL, "q=\"" + begining + "\"");
05b140ed   Nathanael Jourdane   TargetNameField J...
391
392
393
394
395
396
397
398
399
			JsonObject root = new JsonParser().parse(resolverResult.toString()).getAsJsonObject();
			int count = Integer.parseInt(root.get("count").toString());
			String[] targetNames = new String[count];
			JsonArray hits = root.getAsJsonArray("hits");
			for (int i = 0; i < count; i++) {
				JsonObject elmt = hits.get(i).getAsJsonObject();
				targetNames[i] = elmt.get("name").toString().replace("\"", "");
				// TODO: Display "[name] ([type])" on the JComboBox, but only "[name]" on the query.
			}
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
400
			return targetNames;
eb483599   Nathanael Jourdane   Add missing Param...
401
402
		}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
403
		/**
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
404
405
		 * This method is called each time the field is modified.
		 */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
406
407
		@Override
		public void update(JTextField textField) {
3d80f3c3   Nathanael Jourdane   bugFix: targetNam...
408
			SwingUtilities.invokeLater(updateComboBox);
eb483599   Nathanael Jourdane   Add missing Param...
409
410
411
		}
	}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
412
413
414
415
416
417
418
419
420
	/**
	 * The data product type field is used only for the `dataproduct_type` parameter. It is a
	 * ComboBox filled with a list of static data product types (see
	 * https://voparis-confluence.obspm.fr/display/VES/4+-+EPN-TAP+queries#id-4-EPN-TAPqueries-
	 * __RefHeading__35_312326667_Toc3037660444.2.4DataProductType). The parameter is sent to the
	 * controller each time it is updated.
	 * 
	 * @author N. Jourdane
	 */
eb483599   Nathanael Jourdane   Add missing Param...
421
	public static class DataProductTypeField extends ParamField {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
422
		/** The serial version UID (affected with a random number). */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
423
		private static final long serialVersionUID = -6362359909898369750L;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
424
		/** The comboBox used to select the data product type. */
77184f22   Nathanael Jourdane   Use enums for Dat...
425
426
		JComboBox<DataProductType> comboBox;

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
427
428
429
430
431
432
433
434
		/**
		 * An enumeration of all available data product types. Each values comes with an id because
		 * EPN-TAP table can possibly be filled with the id instead of the name, so the query have
		 * to ask for both of them.
		 * 
		 * @author N. Jourdane
		 */
		@SuppressWarnings("javadoc")
77184f22   Nathanael Jourdane   Use enums for Dat...
435
436
		enum DataProductType {
			// @noformat
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
437
438
439
440
			ALL("All", "all"),            IM("Image", "im"),         SP("Spectrum", "sp"),
			DS("Dynamic spectrum", "ds"), SC("Spectral cube", "sc"), PR("Profile", "pr"),
			VO("Volume", "vo"),           MO("Movie", "mo"),         CU("Cube", "cu"),
			TS("Time series", "ts"),      CA("Catalog", "ca"),       SV("Spatial vector", "sv");
77184f22   Nathanael Jourdane   Use enums for Dat...
441
442
			// @format

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
443
			/** The full name of the data product type, such as `Dynamic spectrum`. */
77184f22   Nathanael Jourdane   Use enums for Dat...
444
			private String name = "";
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
445
			/** The id of the data product type, such as `ds`. */
77184f22   Nathanael Jourdane   Use enums for Dat...
446
447
			private String id = "";

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
448
449
450
451
452
453
454
			/**
			 * Method constructor for the enumeration.
			 * 
			 * @param name The full name of the data product type, such as `Dynamic spectrum`.
			 * @param id The id of the data product type, such as `ds`.
			 */
			DataProductType(String name, String id) {
77184f22   Nathanael Jourdane   Use enums for Dat...
455
				this.name = name;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
456
				this.id = id;
77184f22   Nathanael Jourdane   Use enums for Dat...
457
458
			}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
459
460
461
462
463
			/**
			 * @return A list of two strings, containing the name (formated for the query) and the
			 *         id, used in the query. A list is used instead of a array because the getQuery
			 *         function ( @see Queries) needs to know the parameter type.
			 */
77184f22   Nathanael Jourdane   Use enums for Dat...
464
465
466
467
468
469
470
471
472
473
474
475
			public List<String> query() {
				List<String> item = new ArrayList<>();
				item.add(name.replace(" ", "-").toLowerCase());
				item.add(id);
				return item;
			}

			@Override
			public String toString() {
				return name;
			}
		}
667dd80c   Nathanael Jourdane   JTextField as Par...
476

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
477
478
479
480
481
482
		/**
		 * Method constructor
		 * 
		 * @param mainView The main view of the application.
		 * @param paramName The name of the parameter.
		 */
5af53be7   Nathanael Jourdane   Make the applicat...
483
484
		public DataProductTypeField(EpnTapMainView mainView, String paramName) {
			super(mainView, paramName);
77184f22   Nathanael Jourdane   Use enums for Dat...
485
486
			comboBox = new JComboBox<>(DataProductType.values());
			comboBox.setSelectedItem(DataProductType.ALL);
68ae1315   Nathanael Jourdane   Improve GUI appar...
487
			comboBox.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));
a99d92fa   Nathanael Jourdane   Add JComboBox for...
488
489
490
			comboBox.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
491
					update();
a99d92fa   Nathanael Jourdane   Add JComboBox for...
492
493
494
495
496
				}
			});
			this.add(comboBox);
		}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
497
498
499
500
		/**
		 * This method is called each time the field is modified.
		 */
		void update() {
77184f22   Nathanael Jourdane   Use enums for Dat...
501
502
			DataProductType item = (DataProductType) comboBox.getSelectedItem();
			if (DataProductType.ALL.equals(item)) {
4268557f   Nathanael Jourdane   Fix some Sonar is...
503
				mainView.event(Event.PARAMETER_REMOVED, paramName);
5af53be7   Nathanael Jourdane   Make the applicat...
504
			} else {
4268557f   Nathanael Jourdane   Fix some Sonar is...
505
				mainView.event(Event.PARAMETER_CHANGED, paramName, item.query());
5af53be7   Nathanael Jourdane   Make the applicat...
506
			}
eb483599   Nathanael Jourdane   Add missing Param...
507
508
509
		}
	}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
510
511
512
513
514
515
516
517
518
	/**
	 * The target class field is used only for the `target_class` parameter. It is a ComboBox filled
	 * with a list of static target classes (see
	 * https://voparis-confluence.obspm.fr/display/VES/4+-+EPN-TAP+queries#id-4-EPN-TAPqueries-
	 * __RefHeading__39_312326667_Toc3037660464.2.6TargetClass). The parameter is sent to the
	 * controller each time it is updated.
	 * 
	 * @author N. Jourdane
	 */
eb483599   Nathanael Jourdane   Add missing Param...
519
	public static class TargetClassField extends ParamField {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
520
		/** The serial version UID (affected with a random number). */
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
521
		private static final long serialVersionUID = 6439475087727685080L;
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
522
523

		/** The comboBox used to select the target class. */
77184f22   Nathanael Jourdane   Use enums for Dat...
524
525
		JComboBox<TargetClass> comboBox;

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
526
527
528
529
530
531
		/**
		 * An enumeration of all available target classes.
		 * 
		 * @author N. Jourdane
		 */
		@SuppressWarnings("javadoc")
77184f22   Nathanael Jourdane   Use enums for Dat...
532
533
		enum TargetClass {
			// @noformat
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
534
535
536
			ALL("All"),        COMET("Comet"),   EXOPLANET("Exoplanet"),    RING("Ring"),
			SAMPLE("Sample"),  SKY("Sky"),       SPACECRAFT("Spacecraft"),  SPACEJUNK("Spacejunk"),
			STAR("Star"),      INTERPLANETARY_MEDIUM("Interplanetary medium");
77184f22   Nathanael Jourdane   Use enums for Dat...
537
538
			// @format

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
539
			/** The name of the target class. */
77184f22   Nathanael Jourdane   Use enums for Dat...
540
541
			String name;

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
542
543
544
545
546
			/**
			 * Method constructor for the enumeration.
			 * 
			 * @param name The name of the target class.
			 */
77184f22   Nathanael Jourdane   Use enums for Dat...
547
548
549
550
			TargetClass(String name) {
				this.name = name;
			}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
551
552
553
			/**
			 * @return The name formated for the query.
			 */
77184f22   Nathanael Jourdane   Use enums for Dat...
554
555
556
557
			String query() {
				return name.replace(" ", "_").toLowerCase();
			}
		}
667dd80c   Nathanael Jourdane   JTextField as Par...
558

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
559
560
561
562
563
564
		/**
		 * Method constructor
		 * 
		 * @param mainView The main view of the application.
		 * @param paramName The name of the parameter.
		 */
5af53be7   Nathanael Jourdane   Make the applicat...
565
566
		public TargetClassField(EpnTapMainView mainView, String paramName) {
			super(mainView, paramName);
77184f22   Nathanael Jourdane   Use enums for Dat...
567
			comboBox = new JComboBox<>(TargetClass.values());
68ae1315   Nathanael Jourdane   Improve GUI appar...
568
			comboBox.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));
a99d92fa   Nathanael Jourdane   Add JComboBox for...
569
570
571
			comboBox.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
572
					update();
a99d92fa   Nathanael Jourdane   Add JComboBox for...
573
574
575
576
577
				}
			});
			this.add(comboBox);
		}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
578
579
580
581
		/**
		 * This method is called each time the field is modified.
		 */
		void update() {
77184f22   Nathanael Jourdane   Use enums for Dat...
582
583
			TargetClass value = (TargetClass) comboBox.getSelectedItem();
			if (TargetClass.ALL.equals(value)) {
4268557f   Nathanael Jourdane   Fix some Sonar is...
584
				mainView.event(Event.PARAMETER_REMOVED, paramName);
5af53be7   Nathanael Jourdane   Make the applicat...
585
			} else {
4268557f   Nathanael Jourdane   Fix some Sonar is...
586
				mainView.event(Event.PARAMETER_CHANGED, paramName, value.query());
5af53be7   Nathanael Jourdane   Make the applicat...
587
			}
eb483599   Nathanael Jourdane   Add missing Param...
588
589
590
		}
	}

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
591
592
593
594
595
596
597
	/**
	 * The listener of text field, it aims to provide a simple way to listen a text field without to
	 * override removeUpdate(DocumentEvent de), insertUpdate(DocumentEvent de) and
	 * changedUpdate(DocumentEvent de) on each field to listen.
	 * 
	 * @author N. Jourdane
	 */
e97b40e8   Nathanael Jourdane   Make ParamField c...
598
	interface TextFieldListener {
b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
599
600
601
602
603
604
		/**
		 * When the content of the JTextField is updated.
		 * 
		 * @param field The JTextField. Is useful for classes containing several text fields, such
		 *            as DateRangeField, to know which one triggered the event.
		 */
e97b40e8   Nathanael Jourdane   Make ParamField c...
605
606
		void update(JTextField field);
	}
eb483599   Nathanael Jourdane   Add missing Param...
607

b6b4fb3e   Nathanael Jourdane   Add Javadoc for P...
608
609
610
611
612
613
	/**
	 * To add the listener. @see TextFieldListener
	 * 
	 * @param changeListener The listener of text fields.
	 * @param field The field to listen.
	 */
42819b99   Nathanael Jourdane   Make EpnTAPClient...
614
	static void addChangeListener(final TextFieldListener changeListener, final JTextField field) {
e97b40e8   Nathanael Jourdane   Make ParamField c...
615
		field.getDocument().addDocumentListener(new DocumentListener() {
53d49e83   Nathanael Jourdane   Fix all Eclipse w...
616
			@Override
e97b40e8   Nathanael Jourdane   Make ParamField c...
617
618
			public void removeUpdate(DocumentEvent de) {
				changeListener.update(field);
eb483599   Nathanael Jourdane   Add missing Param...
619
620
			}

53d49e83   Nathanael Jourdane   Fix all Eclipse w...
621
			@Override
e97b40e8   Nathanael Jourdane   Make ParamField c...
622
623
			public void insertUpdate(DocumentEvent de) {
				changeListener.update(field);
eb483599   Nathanael Jourdane   Add missing Param...
624
625
			}

53d49e83   Nathanael Jourdane   Fix all Eclipse w...
626
			@Override
e97b40e8   Nathanael Jourdane   Make ParamField c...
627
628
			public void changedUpdate(DocumentEvent de) {
				changeListener.update(field);
eb483599   Nathanael Jourdane   Add missing Param...
629
			}
eb483599   Nathanael Jourdane   Add missing Param...
630
		});
eb483599   Nathanael Jourdane   Add missing Param...
631
632
	}
}