ParamField.java 7.75 KB
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;
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;

public abstract class ParamField extends JPanel {

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

	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));
		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);
		// TODO: Add tooltip text based on rr.table_column.column_description
		this.requestView = requestView;
		this.paramName = paramName;
	}

	public static class StringField extends ParamField {
		StringField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			JTextField field = new JTextField();
			addChangeListener(field, e -> onUpdate(field));
			this.add(field);
		}

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

	public static class FloatField extends ParamField {
		FloatField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			JTextField field = new JTextField();
			addChangeListener(field, e -> onUpdate(field));
			this.add(field);
		}

		private void onUpdate(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 {
		DateRangeField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			JTextField fieldMin = new JTextField();
			addChangeListener(fieldMin, e -> onUpdate(fieldMin, MIN_SUFFIX));
			this.add(fieldMin);

			JTextField fieldMax = new JTextField();
			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 {
		JTextField fieldMin;
		JTextField fieldMax;

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

			fieldMax = new JTextField();
			addChangeListener(fieldMax, e -> onUpdate(fieldMax, MAX_SUFFIX));
			this.add(fieldMax);
		}

		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);
				}
			}
		}
	}

	public static class TargetNameField extends ParamField {
		TargetNameField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			JTextField field = new JTextField();
			addChangeListener(field, e -> onUpdate(field));
			this.add(field);
		}

		private void onUpdate(JTextField field) {
			// TODO: add resolver
			if ("".equals(field.getText())) {
				requestView.updateParam(paramName, null);
			} else {
				requestView.updateParam(paramName, field.getText());
			}
		}
	}

	public static class DataProductTypeField extends ParamField {
		DataProductTypeField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			JTextField field = new JTextField();
			// TODO: listbox with enumerated values instead of JTextField
			addChangeListener(field, e -> onUpdate(field));
			this.add(field);
		}

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

	public static class TargetClassField extends ParamField {
		TargetClassField(RequestView requestView, String paramName) {
			super(requestView, paramName);
			JTextField field = new JTextField();
			// TODO: listbox with enumerated values instead of JTextField
			addChangeListener(field, e -> onUpdate(field));
			this.add(field);
		}

		private void onUpdate(JTextField field) {
			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);
	}
}