From: Jim Procter Date: Thu, 4 May 2017 08:53:10 +0000 (+0100) Subject: Merge branch 'features/JAL-2503_filteronquantitativeannotation' into develop X-Git-Tag: Release_2_10_2~3^2~105^2^2~5 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=f4c01c55eaf4b6781cae2a26fb5bb803ffc99323;hp=3ba37699f5f799d357e0cb6f041f32fc490b6eda;p=jalview.git Merge branch 'features/JAL-2503_filteronquantitativeannotation' into develop --- diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 5ac4269..e63752d 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -68,7 +68,6 @@ action.user_defined = User Defined... action.by_conservation = By Conservation action.wrap = Wrap action.show_gaps = Show Gaps -action.show_occupancy = Show Occupancy action.show_hidden_markers = Show Hidden Markers action.find = Find action.undefine_groups = Undefine Groups @@ -1303,3 +1302,9 @@ warn.name_cannot_be_duplicate = User-defined URL names must be unique and cannot label.invalid_name = Invalid Name ! label.output_seq_details = Output Sequence Details to list all database references label.urllinks = Links +label.quality_descr = Alignment Quality based on Blosum62 scores +label.conservation_descr = Conservation of total alignment less than {0}% gaps +label.consensus_descr = PID +label.complement_consensus_descr = PID for cDNA +label.strucconsensus_descr = PID for base pairs +label.occupancy_descr = Number of aligned positions \ No newline at end of file diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index e959afd..6ddbb44 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -182,6 +182,7 @@ label.score_model_conservation = Conservaci label.score_model_enhconservation = Conservación de las propiedades físico-químicas label.status_bar = Barra de estado label.out_to_textbox = Generar cuadro de texto +label.occupancy = Ocupación label.clustal = Clustal # label.colourScheme_ as in JalviewColourScheme label.colourScheme_clustal = Clustalx @@ -835,6 +836,7 @@ label.webservice_job_title_on = {0} usando {1} de {2} label.updating_vamsas_session = Actualizando sesión VAMSAS label.loading_file = Cargando fichero: {0} label.edit_params = Editar {0} +label.as_percentage = Como Porcentaje error.not_implemented = No implementado error.no_such_method_as_clone1_for = No existe ese método como un clone1 de {0} error.null_from_clone1 = Nulo de clone1! diff --git a/src/jalview/analysis/AAFrequency.java b/src/jalview/analysis/AAFrequency.java index 3636b5e..b806355 100755 --- a/src/jalview/analysis/AAFrequency.java +++ b/src/jalview/analysis/AAFrequency.java @@ -332,9 +332,9 @@ public class AAFrequency final int gapped = profile.getNonGapped(); - String description = ""; + String description = "" + gapped; - gaprow.annotations[i] = new Annotation(description, description, + gaprow.annotations[i] = new Annotation("", description, '\0', gapped, jalview.util.ColorUtils.bleachColour( Color.DARK_GRAY, (float) scale * gapped)); } diff --git a/src/jalview/appletgui/AnnotationColumnChooser.java b/src/jalview/appletgui/AnnotationColumnChooser.java index 4b67bbf..25ff293 100644 --- a/src/jalview/appletgui/AnnotationColumnChooser.java +++ b/src/jalview/appletgui/AnnotationColumnChooser.java @@ -167,20 +167,22 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements } populateThresholdComboBox(threshold); - + AnnotationColumnChooser lastChooser = av + .getAnnotationColumnSelectionState(); // restore Object state from the previous session if one exists - if (av.getAnnotationColumnSelectionState() != null) + if (lastChooser != null) { - currentSearchPanel = av.getAnnotationColumnSelectionState() + currentSearchPanel = lastChooser .getCurrentSearchPanel(); - currentStructureFilterPanel = av.getAnnotationColumnSelectionState() + currentStructureFilterPanel = lastChooser .getCurrentStructureFilterPanel(); - annotations.select(av.getAnnotationColumnSelectionState() + annotations.select(lastChooser .getAnnotations().getSelectedIndex()); - threshold.select(av.getAnnotationColumnSelectionState() + threshold.select(lastChooser .getThreshold().getSelectedIndex()); - actionOption = av.getAnnotationColumnSelectionState() + actionOption = lastChooser .getActionOption(); + percentThreshold.setState(lastChooser.percentThreshold.getState()); } try @@ -243,10 +245,10 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements ngStructureFilterPanel = new StructureFilterPanel(this); thresholdPanel.setTitle("Threshold Filter"); - thresholdPanel.add(percentThreshold); thresholdPanel.add(getThreshold()); thresholdPanel.add(slider); thresholdPanel.add(thresholdValue); + thresholdPanel.add(percentThreshold); actionPanel.add(ok); actionPanel.add(cancel); @@ -318,7 +320,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements { if (!adjusting) { - thresholdValue.setText((slider.getValue() / 1000f) + ""); + setThresholdValueText(); valueChanged(!sliderDragging); } } @@ -404,12 +406,14 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements slider.setEnabled(true); thresholdValue.setEnabled(true); + percentThreshold.setEnabled(true); if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD) { slider.setEnabled(false); thresholdValue.setEnabled(false); thresholdValue.setText(""); + percentThreshold.setEnabled(false); // build filter params } else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD) @@ -434,6 +438,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements // slider.setMajorTickSpacing((int) (range / 10f)); slider.setEnabled(true); thresholdValue.setEnabled(true); + percentThreshold.setEnabled(true); adjusting = false; // build filter params @@ -890,19 +895,8 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements @Override public void actionPerformed(ActionEvent evt) { - if (evt.getSource() == thresholdValue) - { - try - { - float f = new Float(thresholdValue.getText()).floatValue(); - slider.setValue((int) (f * 1000)); - adjustmentValueChanged(null); - } catch (NumberFormatException ex) - { - } - } - else if (evt.getSource() == ok) + if (evt.getSource() == ok) { ok_actionPerformed(null); } diff --git a/src/jalview/appletgui/AnnotationRowFilter.java b/src/jalview/appletgui/AnnotationRowFilter.java index 6ea0fed..315ce3b 100644 --- a/src/jalview/appletgui/AnnotationRowFilter.java +++ b/src/jalview/appletgui/AnnotationRowFilter.java @@ -133,21 +133,26 @@ public abstract class AnnotationRowFilter extends Panel updateView(); } + /** + * update the text field from the threshold slider. preserves state of + * 'adjusting' so safe to call in init. + */ protected void setThresholdValueText() { + boolean oldadj = adjusting; adjusting = true; if (percentThreshold.getState()) { double scl = slider.getMaximum() - slider.getMinimum(); scl = (slider.getValue() - slider.getMinimum()) / scl; - thresholdValue.setText(100 * scl + ""); + thresholdValue.setText(100f * scl + ""); } else { thresholdValue.setText((slider.getValue() / 1000f) + ""); } thresholdValue.setCaretPosition(0); - adjusting = false; + adjusting = oldadj; } public void thresholdValue_actionPerformed(ActionEvent e) @@ -157,15 +162,15 @@ public abstract class AnnotationRowFilter extends Panel float f = Float.parseFloat(thresholdValue.getText()); if (percentThreshold.getState()) { - slider.setValue(slider.getMinimum() - + ((int) ((f / 100f) * (slider.getMaximum() - slider - .getMinimum())))); + int pos = slider.getMinimum() + + (int) ((slider.getMaximum() - slider.getMinimum()) * f / 100f); + slider.setValue(pos); } else { slider.setValue((int) (f * 1000)); } - updateView(); + valueChanged(false); } catch (NumberFormatException ex) { } diff --git a/src/jalview/ext/ensembl/EnsemblRestClient.java b/src/jalview/ext/ensembl/EnsemblRestClient.java index ab3b197..5960f81 100644 --- a/src/jalview/ext/ensembl/EnsemblRestClient.java +++ b/src/jalview/ext/ensembl/EnsemblRestClient.java @@ -57,13 +57,13 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher /* * update these constants when Jalview has been checked / updated for - * changes to Ensembl REST API + * changes to Ensembl REST API (ref JAL-2105) * @see https://github.com/Ensembl/ensembl-rest/wiki/Change-log * @see http://rest.ensembl.org/info/rest?content-type=application/json */ - private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "4.8"; + private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "5.0"; - private static final String LATEST_ENSEMBL_REST_VERSION = "4.8"; + private static final String LATEST_ENSEMBL_REST_VERSION = "5.0"; private static final String REST_CHANGE_LOG = "https://github.com/Ensembl/ensembl-rest/wiki/Change-log"; @@ -513,9 +513,11 @@ abstract class EnsemblRestClient extends EnsemblSequenceFetcher boolean laterVersion = StringUtils.compareVersions(version, expected) == 1; if (laterVersion) { - System.err.println(String.format( - "Expected %s REST version %s but found %s, see %s", - getDbSource(), expected, version, REST_CHANGE_LOG)); + System.err + .println(String + .format("EnsemblRestClient expected %s REST version %s but found %s, see %s", + getDbSource(), expected, version, + REST_CHANGE_LOG)); } info.restVersion = version; } catch (Throwable t) diff --git a/src/jalview/gui/AnnotationColumnChooser.java b/src/jalview/gui/AnnotationColumnChooser.java index 1efc569..73660ec 100644 --- a/src/jalview/gui/AnnotationColumnChooser.java +++ b/src/jalview/gui/AnnotationColumnChooser.java @@ -109,20 +109,23 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements setAnnotations(new JComboBox(getAnnotationItems(false))); populateThresholdComboBox(threshold); - + AnnotationColumnChooser lastChooser = av + .getAnnotationColumnSelectionState(); // restore Object state from the previous session if one exists - if (av.getAnnotationColumnSelectionState() != null) + if (lastChooser != null) { - currentSearchPanel = av.getAnnotationColumnSelectionState() + currentSearchPanel = lastChooser .getCurrentSearchPanel(); - currentStructureFilterPanel = av.getAnnotationColumnSelectionState() + currentStructureFilterPanel = lastChooser .getCurrentStructureFilterPanel(); - annotations.setSelectedIndex(av.getAnnotationColumnSelectionState() + annotations.setSelectedIndex(lastChooser .getAnnotations().getSelectedIndex()); - threshold.setSelectedIndex(av.getAnnotationColumnSelectionState() + threshold.setSelectedIndex(lastChooser .getThreshold().getSelectedIndex()); - actionOption = av.getAnnotationColumnSelectionState() + actionOption = lastChooser .getActionOption(); + percentThreshold.setSelected(lastChooser.percentThreshold + .isSelected()); } try @@ -314,16 +317,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements slider.setMaximum((int) (getCurrentAnnotation().graphMax * 1000)); slider.setValue((int) (getCurrentAnnotation().threshold.value * 1000)); - if (percentThreshold.isSelected()) - { - thresholdValue - .setText("" - + ((getCurrentAnnotation().threshold.value - getCurrentAnnotation().graphMin) * 100f / (getCurrentAnnotation().graphMax - getCurrentAnnotation().graphMin))); - } - else - { - thresholdValue.setText(getCurrentAnnotation().threshold.value + ""); - } + setThresholdValueText(); slider.setMajorTickSpacing((int) (range / 10f)); slider.setEnabled(true); diff --git a/src/jalview/gui/AnnotationRowFilter.java b/src/jalview/gui/AnnotationRowFilter.java index 1035a6c..a3ce528 100644 --- a/src/jalview/gui/AnnotationRowFilter.java +++ b/src/jalview/gui/AnnotationRowFilter.java @@ -129,8 +129,13 @@ public abstract class AnnotationRowFilter extends JPanel }); } + /** + * update the text field from the threshold slider. preserves state of + * 'adjusting' so safe to call in init. + */ protected void setThresholdValueText() { + boolean oldadj = adjusting; adjusting = true; if (percentThreshold.isSelected()) { @@ -141,7 +146,7 @@ public abstract class AnnotationRowFilter extends JPanel { thresholdValue.setText((slider.getValue() / 1000f) + ""); } - adjusting = false; + adjusting = oldadj; } protected void addSliderMouseListeners() { @@ -291,7 +296,7 @@ public abstract class AnnotationRowFilter extends JPanel try { float f = Float.parseFloat(thresholdValue.getText()); - if (percentThreshold.isEnabled()) + if (percentThreshold.isSelected()) { slider.setValue(slider.getMinimum() + ((int) ((f / 100f) * (slider.getMaximum() - slider diff --git a/src/jalview/gui/CalculationChooser.java b/src/jalview/gui/CalculationChooser.java index fe6336e..05f1fba 100644 --- a/src/jalview/gui/CalculationChooser.java +++ b/src/jalview/gui/CalculationChooser.java @@ -47,6 +47,7 @@ import java.util.List; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; +import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; @@ -300,6 +301,7 @@ public class CalculationChooser extends JPanel { ok.setEnabled(false); } + updateScoreModels(comboBox, tips); } /** @@ -340,6 +342,13 @@ public class CalculationChooser extends JPanel } return false; } + + final JComboBox comboBox = new JComboBox(); + + final ComboBoxTooltipRenderer renderer = new ComboBoxTooltipRenderer(); + + List tips = new ArrayList(); + /** * A rather elaborate helper method (blame Swing, not me) that builds a * drop-down list of score models (by name) with descriptions as tooltips. @@ -348,17 +357,14 @@ public class CalculationChooser extends JPanel */ protected JComboBox buildModelOptionsList() { - final JComboBox comboBox = new JComboBox(); - ComboBoxTooltipRenderer renderer = new ComboBoxTooltipRenderer(); comboBox.setRenderer(renderer); - final List tips = new ArrayList(); /* * show tooltip on mouse over the combobox * note the listener has to be on the components that make up * the combobox, doesn't work if just on the combobox */ - MouseAdapter mouseListener = new MouseAdapter() + final MouseAdapter mouseListener = new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) @@ -377,17 +383,39 @@ public class CalculationChooser extends JPanel c.addMouseListener(mouseListener); } + updateScoreModels(comboBox, tips); + + /* + * set the list of tooltips on the combobox's renderer + */ + renderer.setTooltips(tips); + + return comboBox; + } + + private void updateScoreModels(JComboBox comboBox, List tips) + { + Object curSel = comboBox.getSelectedItem(); + tips.clear(); + DefaultComboBoxModel model = new DefaultComboBoxModel(); + /* * now we can actually add entries to the combobox, * remembering their descriptions for tooltips */ ScoreModels scoreModels = ScoreModels.getInstance(); + boolean selectedIsPresent = false; for (ScoreModelI sm : scoreModels.getModels()) { boolean nucleotide = af.getViewport().getAlignment().isNucleotide(); if (sm.isDNA() && nucleotide || sm.isProtein() && !nucleotide) { - comboBox.addItem(sm.getName()); + if (curSel != null && sm.getName().equals(curSel)) + { + selectedIsPresent = true; + curSel = sm.getName(); + } + model.addElement(sm.getName()); /* * tooltip is description if provided, else text lookup with @@ -401,14 +429,13 @@ public class CalculationChooser extends JPanel } tips.add(tooltip); } - - /* - * set the list of tooltips on the combobox's renderer - */ - renderer.setTooltips(tips); } - - return comboBox; + if (selectedIsPresent) + { + model.setSelectedItem(curSel); + } + // finally, update the model + comboBox.setModel(model); } /** diff --git a/src/jalview/viewmodel/AlignmentViewport.java b/src/jalview/viewmodel/AlignmentViewport.java index 0015299..fa3a8a7 100644 --- a/src/jalview/viewmodel/AlignmentViewport.java +++ b/src/jalview/viewmodel/AlignmentViewport.java @@ -62,6 +62,7 @@ import jalview.structure.VamsasSource; import jalview.util.Comparison; import jalview.util.MapList; import jalview.util.MappingUtils; +import jalview.util.MessageManager; import jalview.viewmodel.styles.ViewStyle; import jalview.workers.AlignCalcManager; import jalview.workers.ComplementConsensusThread; @@ -1892,7 +1893,8 @@ public abstract class AlignmentViewport implements AlignViewportI, { initRNAStructure(); } - consensus = new AlignmentAnnotation("Consensus", "PID", + consensus = new AlignmentAnnotation("Consensus", + MessageManager.getString("label.consensus_descr"), new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); initConsensus(consensus); initGapCounts(); @@ -1929,7 +1931,9 @@ public abstract class AlignmentViewport implements AlignViewportI, if (doConsensus) { complementConsensus = new AlignmentAnnotation("cDNA Consensus", - "PID for cDNA", new Annotation[1], 0f, 100f, + MessageManager + .getString("label.complement_consensus_descr"), + new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); initConsensus(complementConsensus); return true; @@ -1957,7 +1961,8 @@ public abstract class AlignmentViewport implements AlignViewportI, if (showOccupancy) { gapcounts = new AlignmentAnnotation("Occupancy", - "Number of aligned positions", new Annotation[1], 0f, + MessageManager.getString("label.occupancy_descr"), + new Annotation[1], 0f, alignment.getHeight(), AlignmentAnnotation.BAR_GRAPH); gapcounts.hasText = true; gapcounts.autoCalculated = true; @@ -1975,8 +1980,8 @@ public abstract class AlignmentViewport implements AlignViewportI, if (conservation == null) { conservation = new AlignmentAnnotation("Conservation", - "Conservation of total alignment less than " - + getConsPercGaps() + "% gaps", new Annotation[1], + MessageManager.formatMessage("label.conservation_descr", + getConsPercGaps()), new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH); conservation.hasText = true; conservation.autoCalculated = true; @@ -1992,7 +1997,7 @@ public abstract class AlignmentViewport implements AlignViewportI, if (quality == null) { quality = new AlignmentAnnotation("Quality", - "Alignment Quality based on Blosum62 scores", + MessageManager.getString("label.quality_descr"), new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH); quality.hasText = true; quality.autoCalculated = true; @@ -2005,7 +2010,8 @@ public abstract class AlignmentViewport implements AlignViewportI, { if (alignment.hasRNAStructure() && strucConsensus == null) { - strucConsensus = new AlignmentAnnotation("StrucConsensus", "PID", + strucConsensus = new AlignmentAnnotation("StrucConsensus", + MessageManager.getString("label.strucconsensus_descr"), new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); strucConsensus.hasText = true; strucConsensus.autoCalculated = true; diff --git a/test/jalview/ws/dbsources/RemoteFormatTest.java b/test/jalview/ws/dbsources/RemoteFormatTest.java new file mode 100644 index 0000000..90d4472 --- /dev/null +++ b/test/jalview/ws/dbsources/RemoteFormatTest.java @@ -0,0 +1,121 @@ +package jalview.ws.dbsources; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import jalview.analysis.AlignSeq; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.DBRefSource; +import jalview.datamodel.SequenceI; +import jalview.ext.ensembl.EnsemblGenomes; +import jalview.fts.api.FTSData; +import jalview.fts.api.FTSDataColumnI; +import jalview.fts.api.FTSRestClientI; +import jalview.fts.core.FTSRestRequest; +import jalview.fts.core.FTSRestResponse; +import jalview.fts.service.uniprot.UniProtFTSRestClient; +import jalview.ws.SequenceFetcher; +import jalview.ws.seqfetcher.DbSourceProxy; + +import java.util.ArrayList; +import java.util.List; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * A class to verify that remotely fetched data has an expected format and can + * be successfully processed by Jalview. This is intended as a first line of + * defence and early warning of service affecting changes to data fetched + * externally. + *

+ * This is class is not intended to cover remote services e.g. alignment. Nor + * should it duplicate tests already provided by other classes (such as + * PDBFTSRestClientTest). Or maybe we will relocate those tests here... + */ +public class RemoteFormatTest +{ + SequenceFetcher sf; + + @BeforeTest(alwaysRun = true) + public void setUp() throws Exception + { + Cache.loadProperties("test/jalview/io/testProps.jvprops"); + // ensure 'add annotation from structure' is selected + Cache.applicationProperties.setProperty("STRUCT_FROM_PDB", + Boolean.TRUE.toString()); + Cache.applicationProperties.setProperty("ADD_SS_ANN", + Boolean.TRUE.toString()); + + sf = new SequenceFetcher(false); + } + + @DataProvider(name = "AccessionData") + protected Object[][] getAccessions() + { + return new Object[][] { { DBRefSource.UNIPROT, "P30419" }, + { DBRefSource.PDB, "1QIP" }, { DBRefSource.EMBL, "X53828" }, + { DBRefSource.EMBLCDS, "CAA37824" }, + { DBRefSource.ENSEMBL, "ENSG00000157764" }, + { new EnsemblGenomes().getDbSource(), "DDB_G0283883" }, + { new PfamFull().getDbSource(), "PF03760" }, + { new PfamSeed().getDbSource(), "PF03760" }, + { new RfamSeed().getDbSource(), "RF00014" } }; + } + + @Test(groups = "Network", dataProvider = "AccessionData") + public void testFetchAccession(String dbSource, String accessionId) + throws Exception + { + System.out.println("Fetching " + accessionId + " from " + dbSource); + List sps = sf.getSourceProxy(dbSource); + assertFalse(sps.isEmpty()); + AlignmentI al = sps.get(0).getSequenceRecords(accessionId); + assertNotNull(al); + assertTrue(al.getHeight() > 0); + SequenceI sq = al.getSequenceAt(0); + // suppress this check as only Uniprot and PDB acquire PDB refs + // assertTrue(sq.getAllPDBEntries().size() > 0, "No PDBEntry on sequence."); + assertTrue(sq.getDBRefs().length > 0, "No DBRef on sequence."); + // suppress this test as only certain databases provide 'primary' dbrefs + // assertFalse(sq.getPrimaryDBRefs().isEmpty()); + int length = AlignSeq.extractGaps("-. ", sq.getSequenceAsString()) + .length(); + assertEquals(sq.getEnd() - sq.getStart() + 1, length, + "Sequence start/end doesn't match number of residues in sequence"); + } + + @Test(groups = { "Network" }) + public void testUniprotFreeTextSearch() throws Exception + { + List wantedFields = new ArrayList(); + FTSRestClientI client = UniProtFTSRestClient.getInstance(); + wantedFields.add(client.getDataColumnByNameOrCode("id")); + wantedFields.add(client.getDataColumnByNameOrCode("entry name")); + wantedFields.add(client.getDataColumnByNameOrCode("organism")); + wantedFields.add(client.getDataColumnByNameOrCode("reviewed")); // Status + wantedFields.add(client.getDataColumnByNameOrCode("length")); + + FTSRestRequest request = new FTSRestRequest(); + request.setAllowEmptySeq(false); + request.setResponseSize(100); + request.setFieldToSearchBy("Search All"); + request.setSearchTerm("metanephrops"); // lobster! + request.setWantedFields(wantedFields); + + FTSRestResponse response; + response = client.executeRequest(request); + assertTrue(response.getNumberOfItemsFound() > 20); + assertTrue(response.getSearchSummary() != null); + assertTrue(response.getSearchSummary().size() > 20); + // verify we successfully filtered out the header row (JAL-2485) + FTSData header = response.getSearchSummary().iterator().next(); + assertFalse( + header.getSummaryData()[0].toString().equalsIgnoreCase("Entry"), + "Failed to filter out summary header row"); + } +}