diff --git a/src/tethys/species/ITISFunctions.java b/src/tethys/species/ITISFunctions.java index 5e3a0709..763c99f3 100644 --- a/src/tethys/species/ITISFunctions.java +++ b/src/tethys/species/ITISFunctions.java @@ -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 searchSpecies(String searchTerm) { + ArrayList items = new ArrayList(); + String xQ = "let $target := \"thespeciessearchterm\" \r\n" + + "return\r\n" + + " {\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" + + " {\r\n" + + " $ranks0/tsn,\r\n" + + " $ranks0/completename,\r\n" + + " \r\n" + + " {string-join($ranks0/vernacular/name, \", \")}\r\n" + + " \r\n" + + " } \r\n" + + "} \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; + } } diff --git a/src/tethys/species/SpeciesTest.java b/src/tethys/species/SpeciesTest.java index 13403f8d..b96f429f 100644 --- a/src/tethys/species/SpeciesTest.java +++ b/src/tethys/species/SpeciesTest.java @@ -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,15 +86,32 @@ public class SpeciesTest { // + " }\r\n" // + "} "; - String xQ = " {\r\n" - + " for $rank0 in collection(\"ITIS_ranks\")/rank[tsn = \"180488\"]\r\n" - + " return\r\n" - + " {\r\n" - + " $rank0/completename\r\n" - + " }\r\n" - + "} "; +// String xQ = " {\r\n" +// + " for $rank0 in collection(\"ITIS_ranks\")/rank[tsn = \"180488\"]\r\n" +// + " return\r\n" +// + " {\r\n" +// + " $rank0/completename\r\n" +// + " }\r\n" +// + "} "; + String xQ = "let $target := \"physeter\" \r\n" + + "return\r\n" + + " {\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" + + " {\r\n" + + " $ranks0/tsn,\r\n" + + " $ranks0/completename,\r\n" + + " \r\n" + + " {string-join($ranks0/vernacular/name, \", \")}\r\n" + + " \r\n" + + " } \r\n" + + "} \r\n" + + ""; + System.out.println(xQ); - JerseyClient jerseyClient = new JerseyClient(uri); Queries queries = new Queries(jerseyClient); diff --git a/src/tethys/species/swing/SpeciesSearchDialog.java b/src/tethys/species/swing/SpeciesSearchDialog.java new file mode 100644 index 00000000..deaa19ad --- /dev/null +++ b/src/tethys/species/swing/SpeciesSearchDialog.java @@ -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 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); + } + + } + +} diff --git a/src/tethys/species/swing/SpeciesSubPanel.java b/src/tethys/species/swing/SpeciesSubPanel.java index 53495f2a..f55919f4 100644 --- a/src/tethys/species/swing/SpeciesSubPanel.java +++ b/src/tethys/species/swing/SpeciesSubPanel.java @@ -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("Either enter a code manually and press \"Find\" for additional information,
" + + "or leave the code empty and press \"Find\" to search the Tethys database using common or scientific names." ); 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()); @@ -128,8 +140,16 @@ public class SpeciesSubPanel { if (itisInfo.getVernacular() != null) { commonName.setText(itisInfo.getVernacular()); } + } + } + + 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()); } -// System.out.println(itisInfo); } public JComponent getDialogComponent() {