ParamField.java 10.4 KB
package eu.omp.irap.vespa.epntapclient.view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

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

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;

public abstract class ParamField extends JPanel {

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

	private static final int MIN_FIELD_WIDTH = 30;
	private static final int FIELD_HEIGHT = 20;
	private static final int MAX_FIELD_WIDTH = 400;
	private static final int LABEL_WIDTH = 140;

	private static final String RESOLVER_URL = "http://voparis-registry.obspm.fr/ssodnet/1/autocomplete";
	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;

	public ParamField(RequestView requestView, String paramName) {
		super();
		this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
		this.setMaximumSize(new Dimension(MAX_FIELD_WIDTH, FIELD_HEIGHT));
		String strLabel = paramName.replaceAll("_", " ").trim();
		JLabel label = new JLabel(strLabel.substring(0, 1).toUpperCase() + strLabel.substring(1));
		label.setPreferredSize(new Dimension(LABEL_WIDTH, FIELD_HEIGHT));
		this.add(label);
		// TODO: Add tooltip text based on rr.table_column.column_description
		this.requestView = requestView;
		this.paramName = paramName;
	}

	public static class StringField extends ParamField implements TextFieldListener {
		JTextField field;

		StringField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			field = new JTextField();
			addChangeListener(this, field);
			this.add(field);
		}

		public void update(JTextField field) {
			if ("".equals(field.getText())) {
				requestView.updateParam(paramName, null);
			} else {
				requestView.updateParam(paramName, field.getText());
			}
		}
	}

	public static class FloatField extends ParamField implements TextFieldListener {
		JTextField field;

		FloatField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			field = new JTextField();
			addChangeListener(this, field);
			this.add(field);
		}

		public void update(JTextField field) {
			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 implements TextFieldListener {
		JTextField fieldMin;
		JTextField fieldMax;

		DateRangeField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			this.add(new JLabel("min "));
			fieldMin = new JTextField();
			fieldMin.setName(MIN_SUFFIX);
			fieldMin.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));
			addChangeListener(this, fieldMin);
			this.add(fieldMin);

			this.add(new JLabel("max "));
			fieldMax = new JTextField();
			fieldMax.setName(MAX_SUFFIX);
			fieldMax.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));
			addChangeListener(this, fieldMin);
			this.add(fieldMax);
		}

		public void update(JTextField field) {
			DateFormat df = new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH);
			if ("".equals(field.getText())) {
				field.setBackground(Color.WHITE);
				requestView.updateParam(paramName + field.getName(), 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 + field.getName(), 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 implements TextFieldListener {
		JTextField fieldMin;
		JTextField fieldMax;

		FloatRangeField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			fieldMin = new JTextField();
			fieldMin.setName(MIN_SUFFIX);
			addChangeListener(this, fieldMin);
			this.add(fieldMin);

			fieldMax = new JTextField();
			fieldMax.setName(MAX_SUFFIX);
			addChangeListener(this, fieldMax);
			this.add(fieldMax);
		}

		public void update(JTextField field) {
			if ("".equals(field.getText())) {
				field.setBackground(Color.WHITE);
				requestView.updateParam(paramName + field.getName(), null);
			} else {
				try {
					requestView.updateParam(paramName + field.getName(),
							Float.parseFloat(field.getText()));
					field.setBackground(Color.WHITE);
				} catch (NumberFormatException e) {
					field.setBackground(Color.PINK);
				}
			}
		}
	}

	public static class TargetNameField extends ParamField implements TextFieldListener {
		JComboBox<String> comboBox;
		JTextField field;
		String lastContent;

		TargetNameField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			comboBox = new JComboBox();
			comboBox.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));

			comboBox.setEditable(true);
			field = (JTextField) comboBox.getEditor().getEditorComponent();
			addChangeListener(this, field);
			this.add(comboBox);
		}

		private String[] getItems(String begining) {
			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.
			}
			return targetNames;
		}

		Runnable updateComboBox = new Runnable() {
			@Override
			public void run() {
				comboBox.removeAllItems();
				for (String s : getItems(lastContent)) {
					comboBox.addItem(s);
				}
			}
		};

		public void update(JTextField field) {
			String content = field.getText();
			if (content.length() >= 2 && !content.equals(lastContent)) {
				lastContent = content;
				SwingUtilities.invokeLater(updateComboBox);
				field.setText(content);
				requestView.updateParam(paramName, content);
			}
		}
	}

	public static class DataProductTypeField extends ParamField {
		JComboBox<String> comboBox;

		DataProductTypeField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			comboBox = new JComboBox(getItems().keySet().toArray());
			comboBox.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));
			comboBox.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					onUpdate();
				}
			});
			this.add(comboBox);
		}

		private HashMap<String, String> getItems() {
			HashMap items = new HashMap<String, String>();
			items.put("All", "all");
			items.put("Image", "im");
			items.put("Spectrum", "sp");
			items.put("Dynamic spectrum", "ds");
			items.put("Spectral cube", "sc");
			items.put("Profile", "pr");
			items.put("Volume", "vo");
			items.put("Movie", "mo");
			items.put("Cube", "cu");
			items.put("Time series", "ts");
			items.put("Catalog", "ca");
			items.put("Spatial vector", "sv");
			return items;
		}

		private void onUpdate() {
			String key = comboBox.getSelectedItem().toString();
			List<String> item = new ArrayList();
			item.add(key.replace(" ", "-").toLowerCase());
			item.add(getItems().get(key));
			requestView.updateParam(paramName, "All".equals(key) ? null : item);
		}
	}

	public static class TargetClassField extends ParamField {
		JComboBox<String> comboBox;

		TargetClassField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			comboBox = new JComboBox(getItems());
			comboBox.setPreferredSize(new Dimension(MIN_FIELD_WIDTH, FIELD_HEIGHT));
			comboBox.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					onUpdate();
				}
			});
			this.add(comboBox);
		}

		private String[] getItems() {
			return new String[] { "All", "Comet", "Exoplanet", "Interplanetary medium", "Ring",
					"Sample", "Sky", "Spacecraft", "Spacejunk", "Star" };
		}

		private void onUpdate() {
			String value = comboBox.getSelectedItem().toString().replace(" ", "_").toLowerCase();
			requestView.updateParam(paramName, "All".equals(value) ? null : value);
		}
	}

	interface TextFieldListener {
		void update(JTextField field);
	}

	static void addChangeListener(TextFieldListener changeListener, JTextField field) {
		field.getDocument().addDocumentListener(new DocumentListener() {
			public void removeUpdate(DocumentEvent de) {
				changeListener.update(field);
			}

			public void insertUpdate(DocumentEvent de) {
				changeListener.update(field);
			}

			public void changedUpdate(DocumentEvent de) {
				changeListener.update(field);
			}
		});
	}
}