Messing around with checking of required fields in nilus objects.

This commit is contained in:
Douglas Gillespie 2024-01-25 18:04:57 +00:00
parent fe33930ca8
commit 88be6ffe2e
17 changed files with 292 additions and 36 deletions

View File

@ -1,7 +1,5 @@
package PamView.wizard;
import java.io.Serializable;
import javax.swing.JPanel;

View File

@ -63,14 +63,7 @@ img {
<a href="tethys_quickstart.html">Next: Quick Start</a>
</p>
<br>
<br>
<p>
List of pages for this module:
</p>
<ol>
<li> <a href="tehtys_quickstart.html">quick start</a> </li>
<li> <a href="tethys_speciescodes.html">specifying species names</li>
</ol>
</body>
</html>

View File

@ -53,6 +53,7 @@ import tethys.output.TethysExportParams;
import tethys.species.ITISFunctions;
import tethys.species.SpeciesMapManager;
import tethys.swing.ProjectDeploymentsDialog;
import tethys.swing.TethysEnabler;
import tethys.swing.TethysTabPanel;
import tethys.swing.XMLStringView;
import tethys.swing.documents.TethysDocumentsFrame;
@ -91,10 +92,12 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
private CalibrationHandler calibrationHandler;
private ITISFunctions itisFunctions;
private TethysEnabler tethysEnabler;
public TethysControl(String unitName) {
super(unitType, unitName);
stateObservers = new ArrayList();
tethysEnabler = new TethysEnabler(this);
dbxmlConnect = new DBXMLConnect(this);
dbxmlQueries = new DBXMLQueries(this, dbxmlConnect);
deploymentHandler = new DeploymentHandler(this);
@ -494,6 +497,7 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
sendStateUpdate(new TethysState(StateType.UPDATESERVER));
}
lastServerStatus = serverState;
tethysEnabler.enableControls(serverState.ok);
return serverState;
}
@ -699,5 +703,12 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
return calibrationHandler;
}
/**
* Get a utility class that enables / disables controls depending on server state.
* @return
*/
public TethysEnabler getEnabler() {
return tethysEnabler;
}
}

View File

@ -1,5 +1,6 @@
package tethys.calibration;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -212,8 +213,10 @@ public class CalibrationHandler implements TethysStateObserver {
// }
// }
addParameterDetails(calDoc, i);
// run some checks of completeness of the data
NilusChecker.removeEmptyFields(calDoc);
// ArrayList<Field> emptyFields = NilusChecker.checkEmptyFields(calDoc);
String calDocName = createDocumentName(calDoc, i);
exists = calDocumentExists(calDocName);

View File

@ -4,6 +4,8 @@ import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComboBox;
@ -15,6 +17,7 @@ import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import PamView.dialog.PamDialog;
import PamView.dialog.PamGridBagContraints;
import PamView.panel.WestAlignedPanel;
import PamView.wizard.PamWizard;
@ -23,9 +26,17 @@ import nilus.AlgorithmType.Parameters;
import nilus.AlgorithmType.SupportSoftware;
import nilus.Calibration;
import nilus.Calibration.QualityAssurance;
import nilus.Helper;
import nilus.QualityValueBasic;
import tethys.calibration.CalibrationHandler;
import tethys.niluswraps.NilusChecker;
/**
* Calibrations Process card attempts to fill in the
* calibration data for the Quality Assurance and Process fields.
* @author dg50
*
*/
public class CalibrationProcessCard extends CalibrationsCard {
private JPanel processPanel;
@ -123,9 +134,13 @@ public class CalibrationProcessCard extends CalibrationsCard {
}
process.setMethod((String) calMethod.getSelectedItem());
process.setVersion(version.getText());
process.setSoftware(software.getText());
String soft = warnNotNull(getPamWizard(), software, "Calibration Method");
if (soft == null) {
return false;
}
process.setSoftware(soft);
if (software.getText() == null) {
getPamWizard().showWarning("You must specify the calibratin method used");
getPamWizard().showWarning("You must specify the calibration method used");
}
QualityAssurance qa = calibration.getQualityAssurance();
@ -133,7 +148,11 @@ public class CalibrationProcessCard extends CalibrationsCard {
qa = new QualityAssurance();
calibration.setQualityAssurance(qa);
}
qa.setComment(qaComment.getText());
String t = warnNotNull(getPamWizard(), qaComment, "QA Comment");
if (t == null) {
return false;
}
qa.setComment(t);
qa.setQuality(QualityValueBasic.fromValue((String) qaQuality.getSelectedItem()));
// need to add a few fixed things for this to work...
@ -142,11 +161,27 @@ public class CalibrationProcessCard extends CalibrationsCard {
if (params == null) {
params = new Parameters();
process.setParameters(params);
// params.getAny().
}
try {
Helper.createRequiredElements(params);
} catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// if (checkEmptyFields(qa) == false) {
// return false;
// }
// if (checkEmptyFields(process) == false) {
//// return false;
// }
return true;
}
@Override
public void setParams(Calibration calibration) {
if (calibration == null) {

View File

@ -3,8 +3,9 @@ package tethys.calibration.swing;
import PamView.wizard.PamWizard;
import PamView.wizard.PamWizardCard;
import nilus.Calibration;
import tethys.swing.TethysWizardCard;
abstract public class CalibrationsCard extends PamWizardCard<Calibration> {
abstract public class CalibrationsCard extends TethysWizardCard<Calibration> {
public CalibrationsCard(PamWizard pamWizard, String title) {
super(pamWizard, title);

View File

@ -28,6 +28,7 @@ import nilus.MetadataInfo;
import nilus.ResponsibleParty;
import tethys.TethysTimeFuncs;
import tethys.calibration.CalibrationHandler;
import tethys.niluswraps.NilusChecker;
import tethys.swing.export.ResponsiblePartyPanel;
public class CalibrationsContactCard extends CalibrationsCard {
@ -125,6 +126,11 @@ public class CalibrationsContactCard extends CalibrationsCard {
}
metaData.setContact(checkRPChildren(metaData.getContact()));
dataManager.getParams(metaData.getContact());
ResponsibleParty metaContact = metaData.getContact();
NilusChecker.removeEmptyFields(metaData);
if (metaData.getContact() == null) {
return PamDialog.showWarning(getPamWizard(), "Missing data", "The Data Manager fields must be completed");
}
metaData.setUpdateFrequency((String) updateInterval.getSelectedItem());
metaData.setDate(TethysTimeFuncs.xmlGregCalFromMillis(System.currentTimeMillis()));
@ -136,6 +142,10 @@ public class CalibrationsContactCard extends CalibrationsCard {
long millis = date.getTime();
cardParams.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(millis));
checkEmptyFields(rp);
checkEmptyFields(metaData);
return true;
}

View File

@ -41,6 +41,7 @@ public class CalibrationsMainPanel extends TethysGUIPanel {
ctrlPanel = new PamPanel(new BorderLayout());
exportButton = new JButton("Export ...");
tethysControl.getEnabler().addComponent(exportButton);
ctrlPanel.add(BorderLayout.WEST, exportButton);
warning = new JLabel();
ctrlPanel.add(BorderLayout.CENTER, warning);

View File

@ -22,6 +22,7 @@ import tethys.Collection;
import tethys.TethysControl;
import tethys.database.TethysActions;
import tethys.database.TethysLogger;
import tethys.niluswraps.NilusChecker;
import tethys.output.TethysExportParams;
import tethys.reporter.TethysReport;
import tethys.reporter.TethysReporter;
@ -146,6 +147,9 @@ public class DBXMLConnect {
*/
public boolean postAndLog(Object nilusObject, String documentName) throws TethysException
{
boolean ok = NilusChecker.warnEmptyFields(tethysControl.getGuiFrame(), nilusObject);
TethysException e = null;
boolean success = false;
try {

View File

@ -1,5 +1,6 @@
package tethys.niluswraps;
import java.awt.Window;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@ -9,6 +10,7 @@ import java.util.List;
import org.renjin.methods.Methods;
import PamView.dialog.warn.WarnOnce;
import nilus.Calibration;
import nilus.Calibration.QualityAssurance;
import nilus.Helper;
@ -45,11 +47,32 @@ public class NilusChecker {
}
}
public static ArrayList<Field> findEmptyFields(Object nilusObject) {
return findEmptyFields(nilusObject, new ArrayList<Field>());
public static boolean warnEmptyFields(Window owner, Object nilusObject) {
ArrayList<Field> emptyFields = findEmptyFields(nilusObject, true);
if (emptyFields == null || emptyFields.size() == 0) {
return true;
}
String msg = String.format("<html>One or more fields in the nilus object %s are required but empty:<br>", nilusObject.getClass().getName());
for (Field f : emptyFields) {
msg += String.format("<br>Field %s in object %s", f.getName(), f.getDeclaringClass().getName());
}
msg += "<br><br>It is likely that this document will fail to write to the Tethys database.</html>";
String tit = "Incomplete Tethys data";
WarnOnce.showWarning(owner, tit, msg, WarnOnce.WARNING_MESSAGE);
return false;
}
public static ArrayList<Field> findEmptyFields(Object nilusObject, ArrayList<Field> found) {
/**
* Find empty fields
* @param nilusObject object to search
* @param onlyRequired only list required fields.
* @return list of empty, and optionally also required, fields.
*/
public static ArrayList<Field> findEmptyFields(Object nilusObject, boolean onlyRequired) {
return findEmptyFields(nilusObject, new ArrayList<Field>(), onlyRequired);
}
private static ArrayList<Field> findEmptyFields(Object nilusObject, ArrayList<Field> found, boolean onlyRequired) {
if (nilusObject == null) {
return found;
}
@ -64,26 +87,26 @@ public class NilusChecker {
for (int i = 0; i < fields.length; i++) {
Method getter = findGetter(fields[i], methods);
if (getter == null) {
System.out.printf("Unable to find getter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
// System.out.printf("Unable to find getter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
continue;
}
// if (setter == null) {
// System.out.printf("Unable to find setter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
// }
boolean required = isRequired(fields[i]);
// System.out.printf("Field %30s is %s required\n", fields[i].getName(), required ? " " : "NOT");
Object gotObj = null;
try {
gotObj = getter.invoke(nilusObject, new Object[0]);
} catch (IllegalAccessException | InvocationTargetException e) {
System.out.printf("Unable to invoce getter %s on %s\n", getter.getName(), nilusObject);
// System.out.printf("Unable to invoce getter %s on %s\n", getter.getName(), nilusObject);
continue;
}
boolean empty = isEmpty(gotObj);
if (empty) {
found.add(fields[i]);
if (required || !onlyRequired) {
found.add(fields[i]);
}
}
else {
found = findEmptyFields(gotObj, found);
found = findEmptyFields(gotObj, found, onlyRequired);
}
}
return found;
@ -113,10 +136,12 @@ public class NilusChecker {
Method getter = findGetter(fields[i], methods);
Method setter = findSetter(fields[i], methods);
if (getter == null) {
System.out.printf("Unable to find getter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
// System.out.printf("Unable to find getter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
continue;
}
if (setter == null) {
System.out.printf("Unable to find setter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
// System.out.printf("Unable to find setter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
continue;
}
boolean required = isRequired(fields[i]);
// System.out.printf("Field %30s is %s required\n", fields[i].getName(), required ? " " : "NOT");
@ -124,13 +149,13 @@ public class NilusChecker {
try {
gotObj = getter.invoke(nilusObject, null);
} catch (IllegalAccessException | InvocationTargetException e) {
System.out.printf("Unable to invoce getter %s on %s\n", getter.getName(), nilusObject);
// System.out.printf("Unable to invoce getter %s on %s\n", getter.getName(), nilusObject);
continue;
}
boolean empty = isEmpty(gotObj);
if (empty && gotObj != null) {
if (empty && gotObj != null && canRemove(fields[i])) {
try {
System.out.printf("Removing empty field %s in object %s\n", fields[i].getName(), nilusObject);
// System.out.printf("Removing empty field %s in object %s\n", fields[i].getName(), nilusObject);
// Object args = new Object[1];
setter.invoke(nilusObject, new Object[1]);
removed++;
@ -146,6 +171,32 @@ public class NilusChecker {
return removed;
}
/**
* Fields that can be removed.
* @param field
* @return
*/
private static boolean canRemove(Field field) {
if (field == null) {
return true;
}
Class fClass = field.getType();
if (fClass == String.class) {
return true;
}
if (List.class.isAssignableFrom(fClass)) {
return false;
}
if (fClass.isPrimitive()) {
return false;
}
String className = fClass.getCanonicalName();
if (className.contains("nilus.")) {
return true;
}
return false;
}
/**
* Check an object for empty and required fields.
* @param nilusObject
@ -179,10 +230,12 @@ public class NilusChecker {
Method getter = findGetter(fields[i], methods);
Method setter = findSetter(fields[i], methods);
if (getter == null) {
System.out.printf("Unable to find getter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
// System.out.printf("Unable to find getter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
continue;
}
if (setter == null) {
System.out.printf("Unable to find setter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
// System.out.printf("Unable to find setter for field %s in %s\n", fields[i].getName(), nilusClass.getName());
continue;
}
boolean required = isRequired(fields[i]);
// System.out.printf("Field %30s is %s required\n", fields[i].getName(), required ? " " : "NOT");
@ -190,7 +243,7 @@ public class NilusChecker {
try {
gotObj = getter.invoke(nilusObject, null);
} catch (IllegalAccessException | InvocationTargetException e) {
System.out.printf("Unable to invoce getter %s on %s\n", getter.getName(), nilusObject);
// System.out.printf("Unable to invoce getter %s on %s\n", getter.getName(), nilusObject);
continue;
}
boolean empty = isEmpty(gotObj);
@ -210,7 +263,7 @@ public class NilusChecker {
}
/**
* See if afield has an annotation that indicates it's required.
* See if a field has an annotation that indicates it's required.
* @param field field
* @return required
*/

View File

@ -14,6 +14,7 @@ import javax.swing.border.TitledBorder;
import PamController.PamController;
import PamView.PamGui;
import PamView.dialog.PamDialog;
import PamView.panel.PamNorthPanel;
import PamguardMVC.PamDataBlock;
import tethys.species.SpeciesMapManager;
@ -39,11 +40,11 @@ public class DataBlockSpeciesDialog extends PamDialog {
});
JPanel nPanel = new JPanel(new BorderLayout());
nPanel.setBorder(new TitledBorder("Code management"));
nPanel.add(BorderLayout.EAST, itisButton);
nPanel.add(BorderLayout.EAST, new PamNorthPanel(itisButton));
String otherMsg =
"<html>Specify an ITIS taxonomic serial number (coding)."
+ "<br>Press the Find button to look up TSNs by Latin or common name. "
+ "Anthropogenic signals should be coded as Homo sapiens (180092). "
+ "<br>Anthropogenic signals should be coded as Homo sapiens (180092). "
+ "<br>Noise Measurements and geophonic sounds should be coded as "
+ "\"Other Phenomena\" (-10). "
+ "<br>When known, a call or sound type should "
@ -62,6 +63,7 @@ public class DataBlockSpeciesDialog extends PamDialog {
mainPanel.add(BorderLayout.NORTH, nPanel);
setDialogComponent(mainPanel);
setResizable(true);
setHelpPoint("utilities.tethys.docs.tethys_speciescodes");
}
protected void gotoITIS() {

View File

@ -78,6 +78,12 @@ public class SpeciesSearchDialog extends PamDialog {
}
});
searchText.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
searchTethys();
}
});
tableModel = new DataModel();
resultTable = new JTable(tableModel);

View File

@ -61,6 +61,7 @@ public class DatablockSynchPanel extends TethysGUIPanel {
mainPanel.add(BorderLayout.CENTER, scrollPane);
PamPanel ctrlPanel = new PamPanel(new BorderLayout());
exportButton = new JButton("Export ...");
tethysControl.getEnabler().addComponent(exportButton);
ctrlPanel.add(BorderLayout.WEST, exportButton);
mainPanel.add(BorderLayout.NORTH, ctrlPanel);

View File

@ -100,6 +100,7 @@ public class DeploymentExportPanel extends TethysGUIPanel implements DeploymentT
addPair("Set from ", projectDeployments, c);
bigExportButton = new JButton("Export selection");
tethysControl.getEnabler().addComponent(bigExportButton);
bigExportButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {

View File

@ -57,6 +57,7 @@ public class DeploymentsPanel extends TethysGUIPanel implements DeploymentTableO
ctrlButtons.setLayout(new BoxLayout(ctrlButtons, BoxLayout.X_AXIS));
optionsButton = new JButton("Options ...");
exportButton = new JButton("Export ...");
tethysControl.getEnabler().addComponent(exportButton);
ctrlButtons.add(optionsButton);
ctrlButtons.add(exportButton);
ctrlPanel.add(BorderLayout.WEST, ctrlButtons);

View File

@ -0,0 +1,56 @@
package tethys.swing;
import java.awt.Component;
import java.util.ArrayList;
import tethys.TethysControl;
import tethys.TethysState;
import tethys.TethysState.StateType;
import tethys.TethysStateObserver;
/**
* Handle enabling / disabling of any buttons / controls on the GUI.
* @author dg50
*
*/
public class TethysEnabler implements TethysStateObserver {
private TethysControl tethysControl;
private ArrayList<Component> components = new ArrayList<>();
/**
* @param tethysControl
*/
public TethysEnabler(TethysControl tethysControl) {
this.tethysControl = tethysControl;
tethysControl.addStateObserver(this);
}
/**
* Add a component to the enable list.
* @param aComponent
*/
public synchronized void addComponent(Component aComponent) {
components.add(aComponent);
}
public synchronized void removeComponent(Component aComponent) {
components.remove(aComponent);
}
@Override
public void updateState(TethysState tethysState) {
// if (tethysState.stateType == StateType.UPDATESERVER) {
// boolean ok = tethysControl.getDbxmlConnect().pingServer()
// }
}
public synchronized void enableControls(boolean enable) {
for (Component c : components) {
c.setEnabled(enable);
}
}
}

View File

@ -0,0 +1,80 @@
package tethys.swing;
import java.awt.Window;
import java.lang.reflect.Field;
import java.util.ArrayList;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;
import PamView.dialog.PamDialog;
import PamView.dialog.warn.WarnOnce;
import PamView.wizard.PamWizard;
import PamView.wizard.PamWizardCard;
import tethys.niluswraps.NilusChecker;
/**
* Wizard card with a few extra functions for Tethys.
* @author dg50
*
* @param <T>
*/
abstract public class TethysWizardCard<T extends Object> extends PamWizardCard<T> {
private static final long serialVersionUID = 1L;
public TethysWizardCard(PamWizard pamWizard, String title) {
super(pamWizard, title);
}
/**
* Get a string out of a text component, but if the field is
* empty, return null rather than an empty, 0 length, string.
* @param textField
* @return string, or null if it's empty.
*/
public String getText(JTextComponent textField) {
String str = textField.getText();
if (str == null) {
return null;
}
if (str.length() == 0) {
return null;
}
return str;
}
/**
* Get a string from a text component, and warn if it is empty or null.
* @param owner parent window for warning
* @param textComponent text component
* @param name control name for warning text
* @return String if there was one, or null if it was null or empty.
*/
public String warnNotNull(Window owner, JTextComponent textComponent, String name) {
String str = getText(textComponent);
if (str != null) {
return str;
}
String warn = String.format("The field %s cannot be empty", name);
PamDialog.showWarning(owner, "Empty or missing data", warn);
return null;
}
/**
* Check for required empty fields.
* @param nilusObject
* @return true if all OK, false if there are required fields
*/
public boolean checkEmptyFields(Object nilusObject) {
NilusChecker.removeEmptyFields(nilusObject);
ArrayList<Field> emptyList = NilusChecker.checkEmptyFields(nilusObject);
if (emptyList.size() == 0) {
return true;
}
Field first = emptyList.get(0);
String msg = String.format("The field \"%s\" in \"%s\" is required by Tethys and must be completed", first.getName(), first.getDeclaringClass().getCanonicalName());
return PamDialog.showWarning(getPamWizard(), "Missing required data", msg);
}
}