Blame view

src/main/java/eu/omp/irap/vespa/epntapclient/view/ParamField.java 9.38 KB
eb483599   Nathanael Jourdane   Add missing Param...
1
2
3
4
5
6
7
8
9
10
11
12
package eu.omp.irap.vespa.epntapclient.view;

import java.awt.Color;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.Objects;

import javax.swing.BoxLayout;
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
13
import javax.swing.JComboBox;
eb483599   Nathanael Jourdane   Add missing Param...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

05b140ed   Nathanael Jourdane   TargetNameField J...
28
29
30
31
32
33
34
35
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableConnection;
import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.BadRequestException;
import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.HTTPRequestException;

eb483599   Nathanael Jourdane   Add missing Param...
36
37
38
39
40
public abstract class ParamField extends JPanel {

	/** The logger for this class. */
	private static final Logger logger = LogManager.getLogger(ParamField.class);

05b140ed   Nathanael Jourdane   TargetNameField J...
41
	private static final String RESOLVER_URL = "http://voparis-registry.obspm.fr/ssodnet/1/autocomplete";
eb483599   Nathanael Jourdane   Add missing Param...
42
43
44
45
46
47
48
49
50
	private static final String DATE_FORMAT = "dd/MM/yyyy";
	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)$)";

	private static final String MIN_SUFFIX = "min";
	private static final String MAX_SUFFIX = "max";

	protected static RequestView requestView;
	protected String paramName;

eb483599   Nathanael Jourdane   Add missing Param...
51
52
53
54
55
56
57
	public ParamField(RequestView requestView, String paramName) {
		super();
		this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
		String strLabel = paramName.replaceAll("_", " ").trim();
		JLabel label = new JLabel(strLabel.substring(0, 1).toUpperCase() + strLabel.substring(1));
		label.setPreferredSize(new Dimension(140, 15));
		this.add(label);
41133475   Nathanael Jourdane   build floatRangeF...
58
		// TODO: Add tooltip text based on rr.table_column.column_description
eb483599   Nathanael Jourdane   Add missing Param...
59
60
61
62
63
		this.requestView = requestView;
		this.paramName = paramName;
	}

	public static class StringField extends ParamField {
667dd80c   Nathanael Jourdane   JTextField as Par...
64
65
		JTextField field;

eb483599   Nathanael Jourdane   Add missing Param...
66
67
		StringField(RequestView requestView, String paramName) {
			super(requestView, paramName);
667dd80c   Nathanael Jourdane   JTextField as Par...
68
69
			field = new JTextField();
			addChangeListener(field, e -> onUpdate());
eb483599   Nathanael Jourdane   Add missing Param...
70
71
72
			this.add(field);
		}

667dd80c   Nathanael Jourdane   JTextField as Par...
73
		private void onUpdate() {
eb483599   Nathanael Jourdane   Add missing Param...
74
75
76
77
78
79
80
81
82
			if ("".equals(field.getText())) {
				requestView.updateParam(paramName, null);
			} else {
				requestView.updateParam(paramName, field.getText());
			}
		}
	}

	public static class FloatField extends ParamField {
667dd80c   Nathanael Jourdane   JTextField as Par...
83
84
		JTextField field;

eb483599   Nathanael Jourdane   Add missing Param...
85
86
		FloatField(RequestView requestView, String paramName) {
			super(requestView, paramName);
667dd80c   Nathanael Jourdane   JTextField as Par...
87
88
			field = new JTextField();
			addChangeListener(field, e -> onUpdate());
eb483599   Nathanael Jourdane   Add missing Param...
89
90
91
			this.add(field);
		}

667dd80c   Nathanael Jourdane   JTextField as Par...
92
		private void onUpdate() {
eb483599   Nathanael Jourdane   Add missing Param...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
			if ("".equals(field.getText())) {
				field.setBackground(Color.WHITE);
				requestView.updateParam(paramName, null);
			} else {
				try {
					requestView.updateParam(paramName, Float.parseFloat(field.getText()));
					field.setBackground(Color.WHITE);
				} catch (NumberFormatException e) {
					field.setBackground(Color.PINK);
				}
			}
		}
	}

	public static class DateRangeField extends ParamField {
667dd80c   Nathanael Jourdane   JTextField as Par...
108
109
110
		JTextField fieldMin;
		JTextField fieldMax;

eb483599   Nathanael Jourdane   Add missing Param...
111
112
		DateRangeField(RequestView requestView, String paramName) {
			super(requestView, paramName);
667dd80c   Nathanael Jourdane   JTextField as Par...
113
			fieldMin = new JTextField();
eb483599   Nathanael Jourdane   Add missing Param...
114
115
116
			addChangeListener(fieldMin, e -> onUpdate(fieldMin, MIN_SUFFIX));
			this.add(fieldMin);

667dd80c   Nathanael Jourdane   JTextField as Par...
117
			fieldMax = new JTextField();
eb483599   Nathanael Jourdane   Add missing Param...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
			addChangeListener(fieldMax, e -> onUpdate(fieldMax, MAX_SUFFIX));
			this.add(fieldMax);
		}

		private void onUpdate(JTextField field, String suffix) {
			DateFormat df = new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH);
			if ("".equals(field.getText())) {
				field.setBackground(Color.WHITE);
				requestView.updateParam(paramName + suffix, null);
			} else if (field.getText().matches(DATE_REGEX)) {
				try {
					long date = df.parse(field.getText()).getTime();
					date = (Math.round((date / 86400000.0) + 2440587.5)); // to JD
					requestView.updateParam(paramName + suffix, date);
					field.setBackground(Color.WHITE);
				} catch (ParseException e) {
					field.setBackground(Color.PINK);
				}
				// TODO: check if date min < date max
			} else {
				field.setBackground(Color.PINK);
			}
		}
	}

	public static class FloatRangeField extends ParamField {
41133475   Nathanael Jourdane   build floatRangeF...
144
145
		JTextField fieldMin;
		JTextField fieldMax;
eb483599   Nathanael Jourdane   Add missing Param...
146
147
148

		FloatRangeField(RequestView requestView, String paramName) {
			super(requestView, paramName);
41133475   Nathanael Jourdane   build floatRangeF...
149
150
			fieldMin = new JTextField();
			addChangeListener(fieldMin, e -> onUpdate(fieldMin, MIN_SUFFIX));
eb483599   Nathanael Jourdane   Add missing Param...
151
152
			this.add(fieldMin);

41133475   Nathanael Jourdane   build floatRangeF...
153
154
			fieldMax = new JTextField();
			addChangeListener(fieldMax, e -> onUpdate(fieldMax, MAX_SUFFIX));
eb483599   Nathanael Jourdane   Add missing Param...
155
156
			this.add(fieldMax);
		}
41133475   Nathanael Jourdane   build floatRangeF...
157
158
159
160
161
162
163
164
165
166
167
168
169
170

		private void onUpdate(JTextField field, String suffix) {
			if ("".equals(field.getText())) {
				field.setBackground(Color.WHITE);
				requestView.updateParam(paramName + suffix, null);
			} else {
				try {
					requestView.updateParam(paramName + suffix, Float.parseFloat(field.getText()));
					field.setBackground(Color.WHITE);
				} catch (NumberFormatException e) {
					field.setBackground(Color.PINK);
				}
			}
		}
eb483599   Nathanael Jourdane   Add missing Param...
171
172
173
	}

	public static class TargetNameField extends ParamField {
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
174
		JComboBox<String> comboBox;
667dd80c   Nathanael Jourdane   JTextField as Par...
175
		JTextField field;
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
176
		String lastContent;
667dd80c   Nathanael Jourdane   JTextField as Par...
177

eb483599   Nathanael Jourdane   Add missing Param...
178
179
		TargetNameField(RequestView requestView, String paramName) {
			super(requestView, paramName);
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
180
181
182
			comboBox = new JComboBox();
			comboBox.setEditable(true);
			field = (JTextField) comboBox.getEditor().getEditorComponent();
667dd80c   Nathanael Jourdane   JTextField as Par...
183
			addChangeListener(field, e -> onUpdate());
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
184
185
186
187
			this.add(comboBox);
		}

		private String[] getTargetNames(String begining) {
05b140ed   Nathanael Jourdane   TargetNameField J...
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
			StringBuilder resolverResult = null;
			try {
				resolverResult = VOTableConnection.sendGet(RESOLVER_URL, "q=\"" + begining + "\"");
			} catch (HTTPRequestException | BadRequestException e) {
				logger.fatal("Can not send sersolver query: ", e);
			}
			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...
203
			return targetNames;
eb483599   Nathanael Jourdane   Add missing Param...
204
205
		}

667dd80c   Nathanael Jourdane   JTextField as Par...
206
		private void onUpdate() {
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
207
208
209
210
211
212
213
214
215
216
			String content = field.getText();
			if (content.length() >= 2 && !content.equals(lastContent)) {
				lastContent = content;
				int nbItems = comboBox.getItemCount();
				comboBox.removeAllItems();
				for (String s : getTargetNames(content)) {
					comboBox.addItem(s);
				}
				field.setText(content);
				requestView.updateParam(paramName, content);
eb483599   Nathanael Jourdane   Add missing Param...
217
218
219
220
221
			}
		}
	}

	public static class DataProductTypeField extends ParamField {
667dd80c   Nathanael Jourdane   JTextField as Par...
222
223
		JTextField field;

eb483599   Nathanael Jourdane   Add missing Param...
224
225
		DataProductTypeField(RequestView requestView, String paramName) {
			super(requestView, paramName);
f00cb6bb   Nathanael Jourdane   Add a JComboBox f...
226
			JTextField field = new JTextField();
eb483599   Nathanael Jourdane   Add missing Param...
227
			// TODO: listbox with enumerated values instead of JTextField
667dd80c   Nathanael Jourdane   JTextField as Par...
228
			addChangeListener(field, e -> onUpdate());
eb483599   Nathanael Jourdane   Add missing Param...
229
230
231
			this.add(field);
		}

667dd80c   Nathanael Jourdane   JTextField as Par...
232
		private void onUpdate() {
eb483599   Nathanael Jourdane   Add missing Param...
233
234
235
236
237
238
239
240
241
			if ("".equals(field.getText())) {
				requestView.updateParam(paramName, null);
			} else {
				requestView.updateParam(paramName, field.getText());
			}
		}
	}

	public static class TargetClassField extends ParamField {
667dd80c   Nathanael Jourdane   JTextField as Par...
242
243
		JTextField field;

eb483599   Nathanael Jourdane   Add missing Param...
244
245
246
247
		TargetClassField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			JTextField field = new JTextField();
			// TODO: listbox with enumerated values instead of JTextField
667dd80c   Nathanael Jourdane   JTextField as Par...
248
			addChangeListener(field, e -> onUpdate());
eb483599   Nathanael Jourdane   Add missing Param...
249
250
251
			this.add(field);
		}

667dd80c   Nathanael Jourdane   JTextField as Par...
252
		private void onUpdate() {
eb483599   Nathanael Jourdane   Add missing Param...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
			if ("".equals(field.getText())) {
				requestView.updateParam(paramName, null);
			} else {
				requestView.updateParam(paramName, field.getText());
			}
		}
	}

	// public class EnumParamField extends ParamField {
	// EnumParamField() {
	// super();
	// }
	// }

	public static void addChangeListener(JTextComponent text, ChangeListener changeListener) {
		Objects.requireNonNull(text);
		Objects.requireNonNull(changeListener);
		DocumentListener dl = new DocumentListener() {
			private int lastChange = 0, lastNotifiedChange = 0;

			@Override
			public void insertUpdate(DocumentEvent e) {
				changedUpdate(e);
			}

			@Override
			public void removeUpdate(DocumentEvent e) {
				changedUpdate(e);
			}

			@Override
			public void changedUpdate(DocumentEvent e) {
				lastChange++;
				SwingUtilities.invokeLater(() -> {
					if (lastNotifiedChange != lastChange) {
						lastNotifiedChange = lastChange;
						changeListener.stateChanged(new ChangeEvent(text));
					}
				});
			}
		};
		text.addPropertyChangeListener("document", (PropertyChangeEvent e) -> {
			Document d1 = (Document) e.getOldValue();
			Document d2 = (Document) e.getNewValue();
			if (d1 != null)
				d1.removeDocumentListener(dl);
			if (d2 != null)
				d2.addDocumentListener(dl);
			dl.changedUpdate(null);
		});
		Document d = text.getDocument();
		if (d != null)
			d.addDocumentListener(dl);
	}
}