001package com.hfg.citation.ncbi;
002
003import java.util.ArrayList;
004import java.util.Calendar;
005import java.util.Date;
006import java.util.GregorianCalendar;
007import java.util.List;
008import java.util.TimeZone;
009import java.util.regex.Matcher;
010import java.util.regex.Pattern;
011
012import com.hfg.bio.seq.format.SeqCitation;
013import com.hfg.citation.Author;
014import com.hfg.citation.Journal;
015import com.hfg.util.BooleanUtil;
016import com.hfg.util.StringUtil;
017import com.hfg.util.collection.CollectionUtil;
018import com.hfg.xml.XMLTag;
019
020//------------------------------------------------------------------------------
021/**
022 Data object for holding MEDLINE citation data.
023 <br/>
024 See: <a href='https://www.nlm.nih.gov/bsd/licensee/elements_descriptions.html'>
025 https://www.nlm.nih.gov/bsd/licensee/elements_descriptions.html</a>
026
027 <div>
028 @author J. Alex Taylor, hairyfatguy.com
029 </div>
030 */
031//------------------------------------------------------------------------------
032// com.hfg XML/HTML Coding Library
033//
034// This library is free software; you can redistribute it and/or
035// modify it under the terms of the GNU Lesser General Public
036// License as published by the Free Software Foundation; either
037// version 2.1 of the License, or (at your option) any later version.
038//
039// This library is distributed in the hope that it will be useful,
040// but WITHOUT ANY WARRANTY; without even the implied warranty of
041// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
042// Lesser General Public License for more details.
043//
044// You should have received a copy of the GNU Lesser General Public
045// License along with this library; if not, write to the Free Software
046// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
047//
048// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
049// jataylor@hairyfatguy.com
050//------------------------------------------------------------------------------
051
052// TODO: Parse ReferenceList
053
054public class MedlineCitation extends SeqCitation
055{
056   private MedlineCitationStatus mStatus;
057   private String mOwner;
058   private Date   mDateCompleted;
059   private Date   mDateRevised;
060   private List<MeshHeading> mMeshHeadings;
061   private List<MedlineCitation> mReferences;
062
063   //###########################################################################
064   // CONSTRUCTORS
065   //###########################################################################
066
067   //---------------------------------------------------------------------------
068   public MedlineCitation()
069   {
070
071   }
072
073   //---------------------------------------------------------------------------
074   public MedlineCitation(XMLTag inXMLTag)
075   {
076      inXMLTag.verifyTagName(PubmedXML.MEDLINE_CITATION);
077
078      String statusString = inXMLTag.getAttributeValue(PubmedXML.STATUS_ATT);
079      if (StringUtil.isSet(statusString))
080      {
081         setStatus(MedlineCitationStatus.valueOf(statusString));
082      }
083
084      setOwner(inXMLTag.getAttributeValue(PubmedXML.OWNER_ATT));
085
086      XMLTag dateCompletedTag = inXMLTag.getOptionalSubtagByName(PubmedXML.DATE_COMPLETED);
087      if (dateCompletedTag != null)
088      {
089         setDateCompleted(parseDateTag(dateCompletedTag));
090      }
091
092      XMLTag dateRevisedTag = inXMLTag.getOptionalSubtagByName(PubmedXML.DATE_REVISED);
093      if (dateRevisedTag != null)
094      {
095         setDateRevised(parseDateTag(dateRevisedTag));
096      }
097
098      XMLTag articleTag = inXMLTag.getOptionalSubtagByName(PubmedXML.ARTICLE);
099      if (articleTag != null)
100      {
101         XMLTag journalTag = articleTag.getOptionalSubtagByName(PubmedXML.JOURNAL);
102         if (journalTag != null)
103         {
104            XMLTag issnTag = journalTag.getOptionalSubtagByName(PubmedXML.ISSN);
105            if (issnTag != null)
106            {
107               setISSN(issnTag.getContent().trim());
108            }
109
110            XMLTag journalIssueTag = journalTag.getOptionalSubtagByName(PubmedXML.JOURNAL_ISSUE);
111            if (journalIssueTag != null)
112            {
113               XMLTag volumeTag = journalIssueTag.getOptionalSubtagByName(PubmedXML.VOLUME);
114               if (volumeTag != null)
115               {
116                  setVolume(volumeTag.getContent());
117               }
118
119               XMLTag issueTag = journalIssueTag.getOptionalSubtagByName(PubmedXML.ISSUE);
120               if (issueTag != null)
121               {
122                  setIssue(issueTag.getContent());
123               }
124
125               XMLTag pubDateTag = journalIssueTag.getOptionalSubtagByName(PubmedXML.PUB_DATE);
126               if (pubDateTag != null)
127               {
128                  setYear(Integer.parseInt(pubDateTag.getRequiredSubtagByName(PubmedXML.YEAR).getContent()));
129               }
130            }
131
132            XMLTag titleTag = journalTag.getOptionalSubtagByName(PubmedXML.TITLE);
133            if (titleTag != null)
134            {
135               Journal journal = new Journal(titleTag.getContent().trim())
136                     .setISSN(getISSN());
137
138               XMLTag abbrevTag = journalTag.getOptionalSubtagByName(PubmedXML.ISO_ABBREVIATION);
139               if (abbrevTag != null)
140               {
141                  journal.setAbbrev(abbrevTag.getContent().trim());
142               }
143
144               setJournal(journal);
145            }
146         }
147
148         XMLTag articleTitleTag = articleTag.getOptionalSubtagByName(PubmedXML.ARTICLE_TITLE);
149         if (articleTitleTag != null)
150         {
151            String title = articleTitleTag.getContent().trim();
152            if (title.endsWith("."))
153            {
154               title = title.substring(0, title.length() - 1);
155            }
156
157            setTitle(title);
158         }
159
160         XMLTag paginationTag = articleTag.getOptionalSubtagByName(PubmedXML.PAGINATION);
161         if (paginationTag != null)
162         {
163            setPages(paginationTag.getRequiredSubtagByName(PubmedXML.MEDLINE_PGN).getContent());
164         }
165
166         XMLTag eLocationIdTag = articleTag.getOptionalSubtagByName(PubmedXML.E_LOCATION_ID);
167         if (eLocationIdTag != null)
168         {
169            if (eLocationIdTag.getAttributeValue(PubmedXML.E_ID_TYPE_ATT).equals("doi"))
170            {
171               setDOI(eLocationIdTag.getContent());
172            }
173         }
174
175
176         XMLTag abstractTag = articleTag.getOptionalSubtagByName(PubmedXML.ABSTRACT);
177         if (abstractTag != null)
178         {
179            setAbstract(abstractTag.getRequiredSubtagByName(PubmedXML.ABSTRACT_TEXT).getContent().trim());
180         }
181
182         XMLTag authorListTag = articleTag.getOptionalSubtagByName(PubmedXML.AUTHOR_LIST);
183         if (authorListTag != null)
184         {
185            List<XMLTag> authorTags = authorListTag.getSubtagsByName(PubmedXML.AUTHOR);
186            for (XMLTag authorTag : authorTags)
187            {
188               String firstName = authorTag.getRequiredSubtagByName(PubmedXML.FORE_NAME).getContent();
189               String lastName = authorTag.getRequiredSubtagByName(PubmedXML.LAST_NAME).getContent();
190               Author author = new Author((StringUtil.isSet(firstName) ? firstName : "") + " " + lastName);
191
192               // TODO: Affiliation
193
194               addAuthor(author);
195            }
196         }
197
198         XMLTag lagnuageTag = articleTag.getOptionalSubtagByName(PubmedXML.LANGUAGE);
199         if (lagnuageTag != null)
200         {
201            setLanguage(lagnuageTag.getContent().trim());
202         }
203      }
204
205      // MeshHeadings (Keywords)
206      XMLTag meshHeadingList = inXMLTag.getOptionalSubtagByName(PubmedXML.MESH_HEADING_LIST);
207      if (meshHeadingList != null)
208      {
209         List<XMLTag> meshHeadingTags = meshHeadingList.getSubtagsByName(PubmedXML.MESH_HEADING);
210         if (CollectionUtil.hasValues(meshHeadingTags))
211         {
212            for (XMLTag meshHeadingTag : meshHeadingTags)
213            {
214               XMLTag descriptorNameTag = meshHeadingTag.getRequiredSubtagByName(PubmedXML.DESCRIPTOR_NAME);
215               MeshHeading meshHeading = new MeshHeading(descriptorNameTag.getContent().trim())
216                     .setUniqueIdentifier(descriptorNameTag.getAttributeValue(PubmedXML.UI_ATT))
217                     .setIsMajorTopic(BooleanUtil.valueOf(descriptorNameTag.getAttributeValue(PubmedXML.MAJOR_TOPIC_YN_ATT)));
218
219               List<XMLTag> meshQualifierTags = meshHeadingTag.getSubtagsByName(PubmedXML.QUALIFIER_NAME);
220               if (CollectionUtil.hasValues(meshQualifierTags))
221               {
222                  for (XMLTag meshQualifierTag : meshQualifierTags)
223                  {
224                     MeshQualifier meshQualifier = new MeshQualifier(meshQualifierTag.getContent().trim())
225                           .setUniqueIdentifier(meshQualifierTag.getAttributeValue(PubmedXML.UI_ATT))
226                           .setIsMajorTopic(BooleanUtil.valueOf(meshQualifierTag.getAttributeValue(PubmedXML.MAJOR_TOPIC_YN_ATT)));
227
228                     meshHeading.addQualifier(meshQualifier);
229                  }
230               }
231
232               addMeshHeading(meshHeading);
233            }
234         }
235      }
236   }
237
238   //###########################################################################
239   // PUBLIC METHODS
240   //###########################################################################
241
242   //---------------------------------------------------------------------------
243   public MedlineCitation setStatus(MedlineCitationStatus inValue)
244   {
245      mStatus = inValue;
246      return this;
247   }
248
249   //---------------------------------------------------------------------------
250   public MedlineCitationStatus getStatus()
251   {
252      return mStatus;
253   }
254
255
256   //---------------------------------------------------------------------------
257   public MedlineCitation setOwner(String inValue)
258   {
259      mOwner = inValue;
260      return this;
261   }
262
263   //---------------------------------------------------------------------------
264   public String getOwner()
265   {
266      return mOwner;
267   }
268
269
270   //---------------------------------------------------------------------------
271   public MedlineCitation setDateCompleted(Date inValue)
272   {
273      mDateCompleted = inValue;
274      return this;
275   }
276
277   //---------------------------------------------------------------------------
278   public Date getDateCompleted()
279   {
280      return mDateCompleted;
281   }
282
283
284   //---------------------------------------------------------------------------
285   public MedlineCitation setDateRevised(Date inValue)
286   {
287      mDateRevised = inValue;
288      return this;
289   }
290
291   //---------------------------------------------------------------------------
292   public Date getDateRevised()
293   {
294      return mDateRevised;
295   }
296
297
298   //---------------------------------------------------------------------------
299   public MedlineCitation addMeshHeading(MeshHeading inValue)
300   {
301      if (null == mMeshHeadings)
302      {
303         mMeshHeadings = new ArrayList<>(10);
304      }
305
306      mMeshHeadings.add(inValue);
307
308      return this;
309   }
310
311   //---------------------------------------------------------------------------
312   public List<MeshHeading> getMeshHeadings()
313   {
314      return mMeshHeadings;
315   }
316
317   //---------------------------------------------------------------------------
318   public MedlineCitation addReference(MedlineCitation inValue)
319   {
320      if (null == mReferences)
321      {
322         mReferences = new ArrayList<>(10);
323      }
324
325      mReferences.add(inValue);
326
327      return this;
328   }
329
330   //---------------------------------------------------------------------------
331   public MedlineCitation setReferences(List<MedlineCitation> inValues)
332   {
333      mReferences = inValues;
334      return this;
335   }
336
337   //---------------------------------------------------------------------------
338   public List<MedlineCitation> getReferences()
339   {
340      return mReferences;
341   }
342
343
344   //###########################################################################
345   // PRIVATE METHODS
346   //###########################################################################
347
348   //---------------------------------------------------------------------------
349   private Date parseDateTag(XMLTag inTag)
350   {
351      GregorianCalendar cal = new GregorianCalendar();
352      cal.setTimeZone(TimeZone.getDefault());
353      cal.set(Calendar.YEAR, Integer.parseInt(inTag.getRequiredSubtagByName(PubmedXML.YEAR).getContent()));
354      cal.set(Calendar.MONTH, Integer.parseInt(inTag.getRequiredSubtagByName(PubmedXML.MONTH).getContent()) - 1);
355      cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(inTag.getRequiredSubtagByName(PubmedXML.DAY).getContent()));
356      cal.set(Calendar.HOUR_OF_DAY, 0);
357      cal.set(Calendar.MINUTE, 0);
358      cal.set(Calendar.SECOND, 0);
359      cal.set(Calendar.MILLISECOND, 0);
360
361      return cal.getTime();
362   }
363}