Skip to content

Commit 705b09c

Browse files
committed
- Added a citation column to the DatasetStatus table so that we don't have to lookup the citation for a saved publicationId.
- Added test: running the pipeline job in "test" mode should not update rows in the DatasetStatus table - Updated PublicationMatch constructor and fromMatchInfo method - Fixed comments, renamed variables, class.
1 parent c76ca1f commit 705b09c

11 files changed

Lines changed: 259 additions & 126 deletions

File tree

panoramapublic/resources/schemas/dbscripts/postgresql/panoramapublic-25.003-25.004.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
ALTER TABLE panoramapublic.DatasetStatus ADD COLUMN PotentialPublicationId VARCHAR(255);
44
ALTER TABLE panoramapublic.DatasetStatus ADD COLUMN PublicationType VARCHAR(50);
55
ALTER TABLE panoramapublic.DatasetStatus ADD COLUMN PublicationMatchInfo TEXT;
6+
ALTER TABLE panoramapublic.DatasetStatus ADD COLUMN Citation TEXT;
67
ALTER TABLE panoramapublic.DatasetStatus ADD COLUMN UserDismissedPublication TIMESTAMP;

panoramapublic/resources/schemas/panoramapublic.xml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,14 +865,17 @@
865865
<column columnName="ExtensionRequestedDate" />
866866
<column columnName="DeletionRequestedDate"/>
867867
<column columnName="PotentialPublicationId">
868-
<description>Cached publication ID (PubMed ID, PMC ID etc.)</description>
868+
<description>Publication ID (PubMed ID, PMC ID) suggestion based on NCBI search</description>
869869
</column>
870870
<column columnName="PublicationType">
871-
<description>Type of publication ID: PMID, PMC, etc.</description>
871+
<description>Type of publication ID: PMID, PMC</description>
872872
</column>
873873
<column columnName="PublicationMatchInfo">
874874
<description>Information about which fields (e.g. PXD, Panorama link, title etc.) matched</description>
875875
</column>
876+
<column columnName="Citation">
877+
<description>NLM citation string for the potential publication match</description>
878+
</column>
876879
<column columnName="UserDismissedPublication">
877880
<description>Date when the user dismissed the publication suggestion for this dataset</description>
878881
</column>

panoramapublic/src/org/labkey/panoramapublic/PanoramaPublicController.java

Lines changed: 75 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@
159159
import org.labkey.panoramapublic.ncbi.NcbiPublicationSearchService;
160160
import org.labkey.panoramapublic.ncbi.NcbiPublicationSearchServiceImpl;
161161
import org.labkey.panoramapublic.ncbi.PublicationMatch;
162+
import org.labkey.panoramapublic.ncbi.NcbiConstants.DB;
162163
import org.labkey.panoramapublic.model.CatalogEntry;
163164
import org.labkey.panoramapublic.model.DataLicense;
164165
import org.labkey.panoramapublic.model.DatasetStatus;
@@ -183,7 +184,6 @@
183184
import org.labkey.panoramapublic.proteomexchange.ChemElement;
184185
import org.labkey.panoramapublic.proteomexchange.ExperimentModificationGetter;
185186
import org.labkey.panoramapublic.proteomexchange.Formula;
186-
import org.labkey.panoramapublic.ncbi.NcbiConstants.DB;
187187
import org.labkey.panoramapublic.proteomexchange.NcbiUtils;
188188
import org.labkey.panoramapublic.proteomexchange.ProteomeXchangeService;
189189
import org.labkey.panoramapublic.proteomexchange.ProteomeXchangeServiceException;
@@ -10300,6 +10300,7 @@ public ModelAndView getView(PrivateDataSendReminderForm form, boolean reshow, Bi
1030010300
// Initialize form with current settings on first view
1030110301
if (!reshow)
1030210302
{
10303+
// Check the "Search for Publications" box if enabled in the saved settings
1030310304
PrivateDataReminderSettings settings = PrivateDataReminderSettings.get();
1030410305
form.setSearchPublications(settings.isEnablePublicationSearch());
1030510306
}
@@ -10670,6 +10671,22 @@ public static class DismissPublicationSuggestionAction extends UpdateDatasetStat
1067010671
{
1067110672
private PublicationMatch _publicationMatch;
1067210673

10674+
@Override
10675+
protected void doValidationForAction(Errors errors)
10676+
{
10677+
_publicationMatch = PublicationMatch.fromDatasetStatus(_datasetStatus);
10678+
10679+
if (_publicationMatch == null)
10680+
{
10681+
errors.reject(ERROR_MSG, "No publication suggestion exists for the data with short URL " + _exptAnnotations.getShortUrl().renderShortURL());
10682+
}
10683+
else if (_datasetStatus.getUserDismissedPublication() != null)
10684+
{
10685+
errors.reject(ERROR_MSG, "The publication suggestion for the data with short URL " + _exptAnnotations.getShortUrl().renderShortURL()
10686+
+ " has already been dismissed");
10687+
}
10688+
}
10689+
1067310690
@Override
1067410691
protected String getConfirmViewTitle()
1067510692
{
@@ -10691,22 +10708,6 @@ protected Renderable getConfirmViewMessage()
1069110708
publicationRef);
1069210709
}
1069310710

10694-
@Override
10695-
protected void doValidationForAction(Errors errors)
10696-
{
10697-
_publicationMatch = PublicationMatch.fromDatasetStatus(_datasetStatus);
10698-
10699-
if (_publicationMatch == null)
10700-
{
10701-
errors.reject(ERROR_MSG, "No publication suggestion exists for the data with short URL " + _exptAnnotations.getShortUrl().renderShortURL());
10702-
}
10703-
else if (_datasetStatus.getUserDismissedPublication() != null)
10704-
{
10705-
errors.reject(ERROR_MSG, "The publication suggestion for the data with short URL " + _exptAnnotations.getShortUrl().renderShortURL()
10706-
+ " has already been dismissed");
10707-
}
10708-
}
10709-
1071010711
// Fetch the citation from NCBI. If NCBI is unavailable, the publication ID label will be used as a fallback.
1071110712
private void fetchCitation()
1071210713
{
@@ -10756,6 +10757,21 @@ public ModelAndView getSuccessView(ShortUrlForm shortUrlForm)
1075610757
}
1075710758
}
1075810759

10760+
public static class ShortUrlForm
10761+
{
10762+
private String _shortUrlEntityId;
10763+
10764+
public String getShortUrlEntityId()
10765+
{
10766+
return _shortUrlEntityId;
10767+
}
10768+
10769+
public void setShortUrlEntityId(String shortUrlEntityId)
10770+
{
10771+
_shortUrlEntityId = shortUrlEntityId;
10772+
}
10773+
}
10774+
1075910775
@RequiresPermission(AdminOperationsPermission.class)
1076010776
public static class SearchPublicationsForDatasetAction extends SimpleViewAction<ExperimentIdForm>
1076110777
{
@@ -10785,21 +10801,17 @@ public ModelAndView getView(ExperimentIdForm form, BindException errors)
1078510801
DatasetStatus datasetStatus = DatasetStatusManager.getForExperiment(_exptAnnotations);
1078610802

1078710803
// Check if any displayed match was dismissed by the user
10788-
boolean showDismissedColumn = false;
10804+
1078910805
String dismissedPubId = null;
10790-
if (datasetStatus != null && datasetStatus.getUserDismissedPublication() != null
10791-
&& datasetStatus.getPotentialPublicationId() != null)
10806+
if (datasetStatus != null)
1079210807
{
10793-
dismissedPubId = datasetStatus.getPotentialPublicationId();
10794-
for (PublicationMatch match : matches)
10795-
{
10796-
if (match.getPublicationId().equals(dismissedPubId))
10797-
{
10798-
showDismissedColumn = true;
10799-
break;
10800-
}
10801-
}
10808+
dismissedPubId = matches.stream()
10809+
.map(PublicationMatch::getPublicationId)
10810+
.filter(datasetStatus::isPublicationDismissed)
10811+
.findFirst()
10812+
.orElse(null);
1080210813
}
10814+
boolean showDismissedColumn = dismissedPubId != null;
1080310815

1080410816
SearchPublicationsForDatasetBean bean = new SearchPublicationsForDatasetBean(_exptAnnotations, matches, showDismissedColumn, dismissedPubId);
1080510817
JspView<SearchPublicationsForDatasetBean> jspView = new JspView<>("/org/labkey/panoramapublic/view/searchPublicationsForDataset.jsp", bean, errors);
@@ -10891,46 +10903,8 @@ public Object execute(ExperimentIdForm form, BindException errors)
1089110903
}
1089210904
}
1089310905

10894-
public static class NotifySubmitterForm extends IdForm
10895-
{
10896-
private String _publicationId;
10897-
private String _publicationType;
10898-
private String _matchInfo;
10899-
10900-
public String getPublicationId()
10901-
{
10902-
return _publicationId;
10903-
}
10904-
10905-
public void setPublicationId(String publicationId)
10906-
{
10907-
_publicationId = publicationId;
10908-
}
10909-
10910-
public String getPublicationType()
10911-
{
10912-
return _publicationType;
10913-
}
10914-
10915-
public void setPublicationType(String publicationType)
10916-
{
10917-
_publicationType = publicationType;
10918-
}
10919-
10920-
public String getMatchInfo()
10921-
{
10922-
return _matchInfo;
10923-
}
10924-
10925-
public void setMatchInfo(String matchInfo)
10926-
{
10927-
_matchInfo = matchInfo;
10928-
}
10929-
10930-
}
10931-
1093210906
@RequiresPermission(AdminOperationsPermission.class)
10933-
public static class NotifySubmitterOfPublicationsAction extends FormHandlerAction<NotifySubmitterForm>
10907+
public static class NotifySubmitterOfPublicationAction extends FormHandlerAction<NotifySubmitterForm>
1093410908
{
1093510909
private Container _announcementsContainer;
1093610910
private Announcement _announcement;
@@ -10960,8 +10934,7 @@ public boolean handlePost(NotifySubmitterForm form, BindException errors) throws
1096010934

1096110935
// Check if the user has already dismissed this publication suggestion
1096210936
DatasetStatus datasetStatus = DatasetStatusManager.getForExperiment(exptAnnotations);
10963-
if (datasetStatus != null && datasetStatus.getUserDismissedPublication() != null
10964-
&& form.getPublicationId().equals(datasetStatus.getPotentialPublicationId()))
10937+
if (datasetStatus != null && datasetStatus.isPublicationDismissed(form.getPublicationId()))
1096510938
{
1096610939
errors.reject(ERROR_MSG, "The user has already dismissed the publication suggestion "
1096710940
+ datasetStatus.getPublicationIdLabel()
@@ -10977,8 +10950,8 @@ public boolean handlePost(NotifySubmitterForm form, BindException errors) throws
1097710950
}
1097810951

1097910952
// Reconstruct PublicationMatch from form fields
10980-
PublicationMatch selectedMatch = PublicationMatch.fromMatchInfo(form.getPublicationId(), pubType, form.getMatchInfo());
10981-
selectedMatch.setCitation(NcbiPublicationSearchService.get().getCitation(form.getPublicationId(), pubType));
10953+
String citation = NcbiPublicationSearchService.get().getCitation(form.getPublicationId(), pubType);
10954+
PublicationMatch selectedMatch = PublicationMatch.fromMatchInfo(form.getPublicationId(), pubType, form.getMatchInfo(), citation);
1098210955

1098310956
// Post notification
1098410957
JournalSubmission submission = SubmissionManager.getSubmissionForExperiment(exptAnnotations);
@@ -11029,6 +11002,7 @@ journal, submission, exptAnnotations, submitter, getUser(), notifyUsers,
1102911002
datasetStatus.setPotentialPublicationId(form.getPublicationId());
1103011003
datasetStatus.setPublicationType(pubType.name());
1103111004
datasetStatus.setPublicationMatchInfo(form.getMatchInfo());
11005+
datasetStatus.setCitation(selectedMatch.getCitation());
1103211006
datasetStatus.setUserDismissedPublication(null);
1103311007
datasetStatus.setLastReminderDate(new Date());
1103411008

@@ -11052,19 +11026,42 @@ public ActionURL getSuccessURL(NotifySubmitterForm form)
1105211026
}
1105311027
}
1105411028

11055-
public static class ShortUrlForm
11029+
public static class NotifySubmitterForm extends IdForm
1105611030
{
11057-
private String _shortUrlEntityId;
11031+
private String _publicationId;
11032+
private String _publicationType;
11033+
private String _matchInfo;
1105811034

11059-
public String getShortUrlEntityId()
11035+
public String getPublicationId()
1106011036
{
11061-
return _shortUrlEntityId;
11037+
return _publicationId;
1106211038
}
1106311039

11064-
public void setShortUrlEntityId(String shortUrlEntityId)
11040+
public void setPublicationId(String publicationId)
1106511041
{
11066-
_shortUrlEntityId = shortUrlEntityId;
11042+
_publicationId = publicationId;
11043+
}
11044+
11045+
public String getPublicationType()
11046+
{
11047+
return _publicationType;
1106711048
}
11049+
11050+
public void setPublicationType(String publicationType)
11051+
{
11052+
_publicationType = publicationType;
11053+
}
11054+
11055+
public String getMatchInfo()
11056+
{
11057+
return _matchInfo;
11058+
}
11059+
11060+
public void setMatchInfo(String matchInfo)
11061+
{
11062+
_matchInfo = matchInfo;
11063+
}
11064+
1106811065
}
1106911066

1107011067
private static ExperimentAnnotations getValidExperimentAnnotations(ShortUrlForm shortUrlForm, Errors errors)

panoramapublic/src/org/labkey/panoramapublic/model/DatasetStatus.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class DatasetStatus extends DbEntity
1616
private String _potentialPublicationId;
1717
private String _publicationType;
1818
private String _publicationMatchInfo;
19+
private String _citation;
1920
private Date _userDismissedPublication;
2021

2122
public int getExperimentAnnotationsId()
@@ -101,7 +102,7 @@ public void setPublicationType(String publicationType)
101102
public String getPublicationIdLabel()
102103
{
103104
NcbiConstants.DB type = NcbiConstants.DB.fromString(_publicationType);
104-
String label = type == null ? (_publicationType != null ? _publicationType : "") : type.getLabel();
105+
String label = type == null ? (_publicationType != null ? _publicationType : "") : type.name();
105106
return label + " ID " + getPotentialPublicationId();
106107
}
107108

@@ -115,6 +116,16 @@ public void setPublicationMatchInfo(String publicationMatchInfo)
115116
_publicationMatchInfo = publicationMatchInfo;
116117
}
117118

119+
public String getCitation()
120+
{
121+
return _citation;
122+
}
123+
124+
public void setCitation(String citation)
125+
{
126+
_citation = citation;
127+
}
128+
118129
public Date getUserDismissedPublication()
119130
{
120131
return _userDismissedPublication;
@@ -124,4 +135,9 @@ public void setUserDismissedPublication(Date userDismissedPublication)
124135
{
125136
_userDismissedPublication = userDismissedPublication;
126137
}
138+
139+
public boolean isPublicationDismissed(String publicationId)
140+
{
141+
return getUserDismissedPublication() != null && publicationId != null && publicationId.equals(getPotentialPublicationId());
142+
}
127143
}

panoramapublic/src/org/labkey/panoramapublic/ncbi/MockNcbiPublicationSearchService.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ public class MockNcbiPublicationSearchService extends NcbiPublicationSearchServi
4646
* Null for pubmed articles (where {@code id} is already the PMID).
4747
* @param title article title
4848
* @param authors comma-separated author list (e.g. "Abbatiello SE,Mani DR,Schilling B")
49-
* @param pubDate publication date string (e.g. "2013 Sep")
49+
* @param pubDate publication date in "YYYY/MM/DD HH:MM" format, matching the NCBI ESummary
50+
* sortpubdate (PubMed) or sortdate (PMC) field that parsePublicationDate() checks first
5051
* @param source journal abbreviation used as ESummary "source" field (e.g. "Mol Cell Proteomics", "bioRxiv")
5152
* @param journalFull full journal name used as ESummary "fulljournalname" field
5253
* @param citation NLM citation string (for getCitation, keyed by PMID; null if not applicable)
@@ -64,7 +65,9 @@ public void register(String database, String id, String searchKey,
6465
metadata.put("sorttitle", title.toLowerCase());
6566
metadata.put("source", source);
6667
metadata.put("fulljournalname", journalFull);
67-
metadata.put("pubdate", pubDate);
68+
// Real NCBI ESummary returns sortpubdate (PubMed) or sortdate (PMC) in "YYYY/MM/DD HH:MM" format.
69+
// parsePublicationDate() checks these first before falling back to pubdate.
70+
metadata.put(isPmc ? "sortdate" : "sortpubdate", pubDate);
6871

6972
// Authors array
7073
JSONArray authorsArray = new JSONArray();

panoramapublic/src/org/labkey/panoramapublic/ncbi/NcbiPublicationSearchService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ static NcbiPublicationSearchService get()
2525

2626
@Nullable Pair<String, String> getPubMedLinkAndCitation(String pubmedId);
2727

28+
/**
29+
* Searches PMC and PubMed for a publication associated with the experiment.
30+
* Returns the top match (highest priority) if multiple matches are found, or null if none.
31+
*/
2832
@Nullable PublicationMatch searchForPublication(@NotNull ExperimentAnnotations expAnnotations, @Nullable Logger logger);
2933

3034
List<PublicationMatch> searchForPublication(@NotNull ExperimentAnnotations expAnnotations, int maxResults, @Nullable Logger logger, boolean getCitations);

0 commit comments

Comments
 (0)