System to search species codes

Search the ITIS species codes in Tethys to find ITIS codes. Search can
be on a common or scientific name.
This commit is contained in:
Douglas Gillespie 2024-01-21 21:35:34 +00:00
parent 54cb0d1b08
commit baff8d140c
4 changed files with 333 additions and 12 deletions

View File

@ -1,14 +1,23 @@
package tethys.species;
import java.io.StringReader;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import PamController.settings.output.xml.PAMGuardXMLPreview;
import PamController.settings.output.xml.PamguardXMLWriter;
import dbxml.Queries;
import tethys.TethysControl;
import tethys.dbxml.DBQueryResult;
import tethys.dbxml.DBXMLConnect;
import tethys.dbxml.DBXMLQueries;
import tethys.dbxml.TethysQueryException;
@ -81,4 +90,83 @@ public class ITISFunctions {
return new TethysITISResult(itisCode, taxunit, latin, vernacular);
}
public ArrayList<SpeciesMapItem> searchSpecies(String searchTerm) {
ArrayList<SpeciesMapItem> items = new ArrayList<SpeciesMapItem>();
String xQ = "let $target := \"thespeciessearchterm\" \r\n"
+ "return\r\n"
+ "<Result xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> {\r\n"
+ "\r\n"
+ " for $ranks0 in collection(\"ITIS_ranks\")/ranks/rank[\r\n"
+ " dbxml:contains(completename, $target) or \r\n"
+ " vernacular[dbxml:contains(name,$target)]]\r\n"
+ "return\r\n"
+ " <Record> {\r\n"
+ " $ranks0/tsn,\r\n"
+ " $ranks0/completename,\r\n"
+ " <vernacular>\r\n"
+ " {string-join($ranks0/vernacular/name, \", \")}\r\n"
+ " </vernacular>\r\n"
+ " } </Record>\r\n"
+ "} </Result>\r\n"
+ "";
xQ = xQ.replace("thespeciessearchterm", searchTerm);
DBXMLConnect dbXMLConnect = tethysControl.getDbxmlConnect();
DBXMLQueries dbxmlQueries = tethysControl.getDbxmlQueries();
Queries queries = dbXMLConnect.getTethysQueries();
String queryResult = null;
try {
queryResult = queries.QueryTethys(xQ);
} catch (Exception e) {
// TODO Auto-generated catch block
// e.printStackTrace();
return items;
}
DocumentBuilder builder = null;
Document doc = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
//Create DocumentBuilder with default configuration
builder = factory.newDocumentBuilder();
//Parse the content to Document object
doc = builder.parse(new InputSource(new StringReader(queryResult)));
} catch (Exception e) {
// e.printStackTrace();
// System.out.println(queryResult);
return items;
}
// print for now, then comment this out..
// PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
// String fDoc = pamXMLWriter.getAsString(doc, true);
// System.out.println(fDoc);
// now unpack the xml document.
NodeList els = doc.getElementsByTagName("Record");
int n = els.getLength();
for (int i = 0; i < n; i++) {
Node aNode = els.item(i);
if (aNode instanceof Element) {
Element anEl = (Element) aNode;
String tsn = dbxmlQueries.getElementData(anEl, "tsn");
int nTSN = 0;
try {
nTSN = Integer.valueOf(tsn);
}
catch (NumberFormatException ex) {
System.out.println("Invalid TSN read from Tethys: " + tsn);
continue;
}
String completeName = dbxmlQueries.getElementData(anEl, "completename");
String vernacular = dbxmlQueries.getElementData(anEl, "vernacular");
SpeciesMapItem mapItem = new SpeciesMapItem(nTSN, "", "", completeName, vernacular);
items.add(mapItem);
}
}
return items;
}
}

View File

@ -21,11 +21,11 @@ public class SpeciesTest {
public static void main(String[] args) {
SpeciesTest st = new SpeciesTest();
st.runJson();
// st.runJson();
// int spermWhale = 180488;
// st.getCodeInfo(spermWhale);
// st.runXQuery();
st.runXQuery();
}
private void getCodeInfo(int itisCode) {
@ -86,14 +86,31 @@ public class SpeciesTest {
// + " }</Deployment>\r\n"
// + "} </Result>";
String xQ = "<Result xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> {\r\n"
+ " for $rank0 in collection(\"ITIS_ranks\")/rank[tsn = \"180488\"]\r\n"
+ " return\r\n"
+ " <rank>{\r\n"
+ " $rank0/completename\r\n"
+ " }</rank>\r\n"
+ "} </Result>";
// String xQ = "<Result xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> {\r\n"
// + " for $rank0 in collection(\"ITIS_ranks\")/rank[tsn = \"180488\"]\r\n"
// + " return\r\n"
// + " <rank>{\r\n"
// + " $rank0/completename\r\n"
// + " }</rank>\r\n"
// + "} </Result>";
String xQ = "let $target := \"physeter\" \r\n"
+ "return\r\n"
+ "<Result xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> {\r\n"
+ "\r\n"
+ " for $ranks0 in collection(\"ITIS_ranks\")/ranks/rank[\r\n"
+ " dbxml:contains(completename, $target) or \r\n"
+ " vernacular[dbxml:contains(name,$target)]]\r\n"
+ "return\r\n"
+ " <Record> {\r\n"
+ " $ranks0/tsn,\r\n"
+ " $ranks0/completename,\r\n"
+ " <vernacular>\r\n"
+ " {string-join($ranks0/vernacular/name, \", \")}\r\n"
+ " </vernacular>\r\n"
+ " } </Record>\r\n"
+ "} </Result>\r\n"
+ "";
System.out.println(xQ);
JerseyClient jerseyClient = new JerseyClient(uri);
Queries queries = new Queries(jerseyClient);

View File

@ -0,0 +1,196 @@
package tethys.species.swing;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.table.AbstractTableModel;
import PamView.dialog.PamDialog;
import PamView.dialog.PamGridBagContraints;
import PamView.tables.SwingTableColumnWidths;
import PamView.tables.TableColumnWidthData;
import tethys.TethysControl;
import tethys.species.ITISFunctions;
import tethys.species.SpeciesMapItem;
public class SpeciesSearchDialog extends PamDialog {
private static final long serialVersionUID = 1L;
private TethysControl tethysControl;
private SpeciesMapItem selectedItem;
private static SpeciesSearchDialog singleInstance;
private JTextField searchText;
private JButton searchButton;
private JTable resultTable;
private ArrayList<SpeciesMapItem> speciesMapItems;
private DataModel tableModel;
private int selectedRow = -1;
private SpeciesSearchDialog(Window parentFrame, TethysControl tethysControl) {
super(parentFrame, "Species search", false);
this.tethysControl = tethysControl;
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.setBorder(new TitledBorder("Search Term"));
JPanel topPanel = new JPanel(new GridBagLayout());
GridBagConstraints c = new PamGridBagContraints();
topPanel.add(new JLabel("Latin or common name ", JLabel.RIGHT), c);
c.gridx++;
topPanel.add(searchText = new JTextField(12), c);
c.gridx++;
topPanel.add(searchButton = new JButton("search"), c);
mainPanel.add(BorderLayout.NORTH, topPanel);
searchButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
searchTethys();
}
});
tableModel = new DataModel();
resultTable = new JTable(tableModel);
JPanel centPanel = new JPanel(new BorderLayout());
centPanel.add(BorderLayout.NORTH, new JLabel("Possible matches", JLabel.LEFT));
JScrollPane scrollPane = new JScrollPane(resultTable);
centPanel.add(BorderLayout.CENTER, scrollPane);
mainPanel.add(BorderLayout.CENTER, centPanel);
resultTable.addMouseListener(new TableMouse());
new SwingTableColumnWidths("Species Search Dialog Table", resultTable);
setResizable(true);
setDialogComponent(mainPanel);
}
public static SpeciesMapItem showDialog(Window parentFrame, TethysControl tethysControl) {
singleInstance = new SpeciesSearchDialog(parentFrame, tethysControl);
singleInstance.setParams();
singleInstance.setVisible(true);
return singleInstance.selectedItem;
}
private void searchTethys() {
clearResults();
String str = searchText.getText();
if (str == null || str.length() == 0) {
return;
}
ITISFunctions itisFunctions = tethysControl.getItisFunctions();
speciesMapItems = itisFunctions.searchSpecies(str);
tableModel.fireTableDataChanged();
}
private void setParams() {
searchText.setText(null);
clearResults();
}
private void clearResults() {
selectedRow = -1;
speciesMapItems = null;
selectedItem = null;
}
@Override
public boolean getParams() {
if (selectedItem == null) {
return showWarning("You must select a row from the table of species");
}
return selectedItem != null;
}
@Override
public void cancelButtonPressed() {
clearResults();
}
@Override
public void restoreDefaultSettings() {
// TODO Auto-generated method stub
}
private class TableMouse extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
selectedRow = resultTable.getSelectedRow();
if (selectedRow >= 0) {
selectedItem = speciesMapItems.get(selectedRow);
}
tableModel.fireTableDataChanged();
}
}
private class DataModel extends AbstractTableModel {
private String[] colNames = {"Select", "TSN", "Name", "Common Name"};
@Override
public int getRowCount() {
if (speciesMapItems == null) {
return 0;
}
return speciesMapItems.size();
}
@Override
public int getColumnCount() {
return colNames.length;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
SpeciesMapItem mapItem = speciesMapItems.get(rowIndex);
switch (columnIndex) {
case 0:
return rowIndex == selectedRow;
case 1:
return mapItem.getItisCode();
case 2:
return mapItem.getLatinName();
case 3:
return mapItem.getCommonName();
}
return null;
}
@Override
public String getColumnName(int column) {
return colNames[column];
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0) {
return Boolean.class;
}
return super.getColumnClass(columnIndex);
}
}
}

View File

@ -85,7 +85,8 @@ public class SpeciesSubPanel {
pamguardName.setToolTipText("Internal name within PAMGuard module");
itisCode.setToolTipText("ITIS species code");
searchButton.setToolTipText("Search for species code");
searchButton.setToolTipText("<html>Either enter a code manually and press \"Find\" for additional information,<br>"
+ "or leave the code empty and press \"Find\" to search the Tethys database using common or scientific names.</html>" );
callType.setToolTipText("Descriptive name for call type or measurement");
latinName.setToolTipText("Scientific name");
commonName.setToolTipText("Common name");
@ -112,6 +113,17 @@ public class SpeciesSubPanel {
return;
}
ITISFunctions itisFunctions = tethysControl.getItisFunctions();
String itisString = this.itisCode.getText();
if (itisString == null || itisString.length() == 0) {
searchForCode(tethysControl, itisFunctions);
}
else {
getCodeInformation(tethysControl, itisFunctions, itisString);
}
// System.out.println(itisInfo);
}
private void getCodeInformation(TethysControl tethysControl, ITISFunctions itisFunctions, String itisString) {
int itisCode = 0;
try {
itisCode = Integer.valueOf(this.itisCode.getText());
@ -129,7 +141,15 @@ public class SpeciesSubPanel {
commonName.setText(itisInfo.getVernacular());
}
}
// System.out.println(itisInfo);
}
private void searchForCode(TethysControl tethysControl, ITISFunctions itisFunctions) {
SpeciesMapItem speciesItem = SpeciesSearchDialog.showDialog(tethysControl.getGuiFrame(), tethysControl);
if (speciesItem != null) {
itisCode.setText(String.format("%d", speciesItem.getItisCode()));
latinName.setText(speciesItem.getLatinName());
commonName.setText(speciesItem.getCommonName());
}
}
public JComponent getDialogComponent() {