/* mla2api.c * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information (NCBI) * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government do not place any restriction on its use or reproduction. * We would, however, appreciate having the NCBI and the author cited in * any work or product based on this material * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * =========================================================================== * * File Name: mla2api.c * * Author: Jonathan Kans * * Version Creation Date: 1/30/07 * * $Revision: 1.21 $ * * File Description: * * Modifications: * -------------------------------------------------------------------------- * * ========================================================================== */ #include #include #include /* low-level connection functions */ NLM_EXTERN CONN Mla2OpenConnection (void) { return QUERY_OpenServiceQuery ("MedArch", NULL, 30); } #ifdef OS_MAC #include #endif NLM_EXTERN MlaBackPtr Mla2WaitForReply ( CONN conn ) { AsnIoConnPtr aicp; time_t currtime, starttime; time_t max = 0; MlaBackPtr mbp = NULL; EIO_Status status; STimeout timeout; #ifdef OS_MAC EventRecord currEvent; #endif if (conn == NULL) return NULL; #ifdef OS_MAC timeout.sec = 0; timeout.usec = 0; #else timeout.sec = 100; timeout.usec = 0; #endif starttime = GetSecs (); while ((status = CONN_Wait (conn, eIO_Read, &timeout)) == eIO_Timeout && max < 300) { currtime = GetSecs (); max = currtime - starttime; #ifdef OS_MAC WaitNextEvent (0, &currEvent, 0, NULL); #endif } if (status == eIO_Success) { aicp = QUERY_AsnIoConnOpen ("rb", conn); mbp = MlaBackAsnRead (aicp->aip, NULL); QUERY_AsnIoConnClose (aicp); } CONN_Close (conn); return mbp; } /* high-level connection functions */ NLM_EXTERN MlaBackPtr Mla2SynchronousQuery ( MlaRequestPtr mrp ) { AsnIoConnPtr aicp; CONN conn; MlaBackPtr mbp = NULL; if (mrp == NULL) return NULL; conn = Mla2OpenConnection (); if (conn == NULL) return NULL; aicp = QUERY_AsnIoConnOpen ("wb", conn); MlaRequestAsnWrite (mrp, aicp->aip, NULL); AsnIoFlush (aicp->aip); QUERY_AsnIoConnClose (aicp); QUERY_SendQuery (conn); mbp = Mla2WaitForReply (conn); return mbp; } NLM_EXTERN Boolean Mla2AsynchronousQuery ( MlaRequestPtr mrp, QUEUE* queue, QueryResultProc resultproc, VoidPtr userdata ) { AsnIoConnPtr aicp; CONN conn; if (mrp == NULL) return FALSE; conn = Mla2OpenConnection (); if (conn == NULL) return FALSE; aicp = QUERY_AsnIoConnOpen ("wb", conn); Mla2RequestAsnWrite (mrp, aicp->aip, NULL); AsnIoFlush (aicp->aip); QUERY_AsnIoConnClose (aicp); QUERY_SendQuery (conn); QUERY_AddToQueue (queue, conn, resultproc, userdata, TRUE); return TRUE; } NLM_EXTERN Int4 Mla2CheckQueue ( QUEUE* queue ) { return QUERY_CheckQueue (queue); } NLM_EXTERN MlaBackPtr Mla2ReadReply ( CONN conn, EIO_Status status ) { AsnIoConnPtr aicp; MlaBackPtr mbp = NULL; if (conn != NULL && status == eIO_Success) { aicp = QUERY_AsnIoConnOpen ("rb", conn); mbp = Mla2BackAsnRead (aicp->aip, NULL); QUERY_AsnIoConnClose (aicp); } return mbp; } /* request creation functions */ NLM_EXTERN MlaRequestPtr Mla2CreateJournalTitleRequest ( CharPtr journal_name ) { ValNodePtr jta; MlaRequestPtr mrp; TitleMsgPtr tmp; if (StringHasNoText (journal_name)) return NULL; jta = ValNodeNew (NULL); jta->choice = Title_type_name; jta->data.ptrvalue = StringSave (journal_name); tmp = TitleMsgNew (); tmp->type = Title_type_all; tmp->title = jta; mrp = ValNodeNew (NULL); mrp->choice = MlaRequest_gettitle; mrp->data.ptrvalue = (Pointer) tmp; return mrp; } NLM_EXTERN MlaRequestPtr Mla2CreateCitArtJournalRequest ( CitArtPtr cap ) { CitJourPtr cjp; CharPtr str; ValNodePtr ttl; if (cap == NULL) return NULL; if (cap->from != 1) return NULL; cjp = (CitJourPtr) cap->fromptr; if (cjp == NULL) return NULL; for (ttl = cjp->title; ttl != NULL; ttl = ttl->next) { if (ttl->choice == Cit_title_name || ttl->choice == Cit_title_trans || ttl->choice == Cit_title_jta || ttl->choice == Cit_title_iso_jta || ttl->choice == Cit_title_ml_jta || ttl->choice == Cit_title_coden || ttl->choice == Cit_title_issn) { str = (CharPtr) ttl->data.ptrvalue; if (StringHasNoText (str)) continue; return Mla2CreateJournalTitleRequest (str); } } return NULL; } NLM_EXTERN MlaRequestPtr Mla2CreateCitArtMatchRequest ( CitArtPtr cap ) { MlaRequestPtr mrp; ValNodePtr pub; if (cap == NULL) return NULL; cap = AsnIoMemCopy ((Pointer) cap, (AsnReadFunc) CitArtAsnRead, (AsnWriteFunc) CitArtAsnWrite); pub = ValNodeNew (NULL); pub->choice = PUB_Article; pub->data.ptrvalue = cap; mrp = ValNodeNew (NULL); mrp->choice = MlaRequest_citmatch; mrp->data.ptrvalue = (Pointer) pub; return mrp; } NLM_EXTERN MlaRequestPtr Mla2CreateCitationtMatchRequest ( CharPtr author, CharPtr journal, CharPtr volume, CharPtr page, Int4 year, CharPtr title ) { AuthListPtr alp; AuthorPtr ap; CitArtPtr cap; CitJourPtr cjp; DatePtr dp; ImprintPtr imp; ValNodePtr jta; MlaRequestPtr mrp; ValNodePtr names; NameStdPtr nsp; PersonIdPtr pid; ValNodePtr pub; ValNodePtr ttl; if (StringHasNoText (author) || StringHasNoText (journal) || year < 1900) return NULL; cap = CitArtNew (); if (cap == NULL) return NULL; nsp = NameStdNew (); nsp->names [0] = StringSave (author); pid = PersonIdNew (); pid->choice = 2; pid->data = nsp; ap = AuthorNew (); ap->name = pid; names = ValNodeNew (NULL); names->choice = 1; names->data.ptrvalue = ap; alp = AuthListNew (); alp->choice = 1; alp->names = names; cap->authors = alp; jta = ValNodeNew (NULL); jta->choice = Title_type_name; jta->data.ptrvalue = StringSave (journal); cjp = CitJourNew (); cjp->title = jta; dp = DateNew (); dp->data [0] = 1; dp->data [1] = year - 1900; imp = ImprintNew (); imp->date = dp; imp->volume = StringSaveNoNull (volume); imp->pages = StringSaveNoNull (page); cjp->imp = imp; cap->from = 1; cap->fromptr = cjp; if (StringDoesHaveText (title)) { ttl = ValNodeNew (NULL); ttl->choice = Title_type_name; ttl->data.ptrvalue = StringSave (title); cap->title = ttl; } pub = ValNodeNew (NULL); pub->choice = PUB_Article; pub->data.ptrvalue = cap; mrp = ValNodeNew (NULL); mrp->choice = MlaRequest_citmatch; mrp->data.ptrvalue = (Pointer) pub; return mrp; } NLM_EXTERN MlaRequestPtr Mla2CreatePubFetchRequest ( Int4 pmid ) { MlaRequestPtr mrp; if (pmid < 1) return NULL; mrp = ValNodeNew (NULL); mrp->choice = MlaRequest_getpub; mrp->data.intvalue = pmid; return mrp; } /* reply extraction functions */ NLM_EXTERN TitleMsgListPtr Mla2ExtractJournalTitleReply ( MlaBackPtr mbp ) { TitleMsgListPtr tlp; if (mbp == NULL || mbp->choice != MlaBack_gettitle) return NULL; tlp = (TitleMsgListPtr) mbp->data.ptrvalue; if (tlp == NULL) return NULL; mbp->data.ptrvalue = NULL; return tlp; } NLM_EXTERN Int4 Mla2ExtractCitMatchReply ( MlaBackPtr mbp ) { Int4 pmid; if (mbp == NULL || mbp->choice != MlaBack_citmatch) return 0; pmid = (Int4) mbp->data.intvalue; if (pmid < 1) return 0; return pmid; } NLM_EXTERN CitArtPtr Mla2ExtractPubFetchReply ( MlaBackPtr mbp ) { CitArtPtr cap; ValNodePtr pub; if (mbp == NULL || mbp->choice != MlaBack_getpub) return NULL; pub = mbp->data.ptrvalue; if (pub == NULL || pub->choice != PUB_Article) return NULL; cap = (CitArtPtr) pub->data.ptrvalue; if (cap == NULL) return NULL; pub->data.ptrvalue = NULL; return cap; } /* utility functions */ /* ml to std code modified from original in medutil.c and then in pmfapi.c */ static Boolean StrIsAllUpperCase ( CharPtr p ) { Char ch; if (p == NULL) return FALSE; ch = *p; while (ch != '\0') { if (! IS_UPPER (ch)) return FALSE; p++; ch = *p; } return TRUE; } static void SplitMLAuthName ( CharPtr name, CharPtr last, CharPtr initials, CharPtr suffix ) { CharPtr p, p2; Int2 i; Char sbuf [40], ibuf [40]; /* Clear the ibuf field and transfer the entire name to 'last', excluding leading and trailing spaces */ if (name == NULL) return; ibuf [0] = '\0'; sbuf [0] = '\0'; last [0] = '\0'; initials [0] = '\0'; suffix [0] = '\0'; while (*name <= ' ') { name++; if (*name == '\0') return; } StringCpy( last, name ); for (i=StringLen (last) - 1; ((i >= 0) && (last [i] <= ' ')); i--) { last[i] = '\0'; } /* Strip off the last token (initials or name suffix (Jr, Sr, suffix.) */ p = StringRChr (last, (int) ' '); if (p != NULL) { /* more than just last name */ /* Separate the token from the last name */ p2 = p + 1; while ((p > last) && (*p == ' ')) { *p = '\0'; p--; } /* If the last token is not all upper case, and there are more than two tokens, see if the next to the last are initials (upper case) */ if (! StrIsAllUpperCase (p2) && (p = StringRChr (last, (int) ' ' )) != NULL) { /* We have at least three tokens, is the next to last initials? */ if (StrIsAllUpperCase (p + 1)) { /* Yes - concatenate the last two tokens as initials */ StringCpy (ibuf, p + 1); StringCpy (sbuf, p2); while (p > last && (*p == ' ')) { *p = '\0'; p--; } } } if (ibuf [0] == '\0') { /* Only the last token goes in ibuf */ StringCpy (ibuf, p2); } } /* now add periods to ibuf and convert suffix */ for (p = initials, p2 = ibuf; *p2 != '\0'; p2++, p++) { *p = *p2; if (! IS_LOWER(*(p2 + 1))) { /* watch out for foreign names */ p++; *p = '.'; } } *p = '\0'; if (sbuf [0]) { if (StringCmp (sbuf, "1d") == 0 || StringCmp (sbuf, "1st") == 0) p = StringMove (suffix, "I"); else if (StringCmp (sbuf, "2d") == 0 || StringCmp (sbuf, "2nd") == 0) p = StringMove (suffix, "II"); else if (StringCmp (sbuf, "3d") == 0 || StringCmp (sbuf, "3rd") == 0) p = StringMove (suffix, "III"); else if (StringCmp (sbuf, "4th") == 0) p = StringMove (suffix, "IV"); else if (StringCmp (sbuf, "5th") == 0) p = StringMove (suffix, "V"); else if (StringCmp (sbuf, "6th") == 0) p = StringMove (suffix, "VI"); else if (StringCmp (sbuf, "Sr") == 0) p = StringMove (suffix, "Sr."); else if (StringCmp (sbuf, "Jr") == 0) p = StringMove (suffix, "Jr."); else p = StringMove (suffix, sbuf); } } static ValNodePtr ChangeMLtoSTD ( CharPtr token ) { AuthorPtr aup; CharPtr eptr; Char last [180], initials [40], suffix [40]; NameStdPtr nsp; PersonIdPtr pid; ValNodePtr vnp; if (token == NULL) return NULL; for (eptr = token + StringLen (token) - 1; eptr > token && *eptr == ' '; eptr--) continue; SplitMLAuthName (token, last, initials, suffix); nsp = NameStdNew (); if (nsp == NULL) return NULL; nsp->names [0] = StringSave (last); if (initials [0] != '\0') { nsp->names[4] = StringSave (initials); } if (suffix[0] != '\0') { nsp->names[5] = StringSave (suffix); } if (nsp->names[0] != NULL) { pid = PersonIdNew (); pid->choice = 2; /* name */ pid->data = nsp; aup = AuthorNew (); aup->name = pid; vnp = ValNodeNew (NULL); vnp->data.ptrvalue = (Pointer) aup; return vnp; } return NULL; } NLM_EXTERN void ChangeCitArtMLAuthorsToSTD ( CitArtPtr cap ) { AuthListPtr alp; AuthorPtr ap; ValNodePtr curr, last = NULL, names, oldnames, tmp; PersonIdPtr pid; CharPtr str; if (cap == NULL) return; alp = cap->authors; if (alp == NULL) return; if (alp->choice == 1) { for (names = alp->names; names != NULL; names = names->next) { ap = names->data.ptrvalue; if (ap == NULL) continue; pid = ap->name; if (pid == NULL) continue; if (pid->choice != 3) continue; str = (CharPtr) pid->data; if (StringHasNoText (str)) continue; curr = ChangeMLtoSTD (str); if (curr == NULL) continue; names->data.ptrvalue = AuthorFree (ap); names->data.ptrvalue = curr->data.ptrvalue; /* do not ValNodeFreeData, since data has been switched to old author */ ValNodeFree (curr); } } if (alp->choice == 2) { /* do not convert if too big for buffers */ for (tmp = alp->names; tmp != NULL; tmp = tmp->next) { if (StringLen ((CharPtr) tmp->data.ptrvalue) > 170) return; } oldnames = alp->names; alp->names = NULL; alp->choice = 1; /* make std names */ for (tmp = oldnames; tmp != NULL; tmp = tmp->next) { curr = ChangeMLtoSTD ((CharPtr) tmp->data.ptrvalue); if (alp->names == NULL) { alp->names = curr; } if (last != NULL) { last->next = curr; } last = curr; } ValNodeFreeData (oldnames); } } NLM_EXTERN void ChangeMlaBackMLAuthorsToSTD ( MlaBackPtr mbp ) { CitArtPtr cap; ValNodePtr pub; if (mbp == NULL || mbp->choice != MlaBack_getpub) return; pub = mbp->data.ptrvalue; if (pub == NULL || pub->choice != PUB_Article) return; cap = (CitArtPtr) pub->data.ptrvalue; if (cap == NULL) return; ChangeCitArtMLAuthorsToSTD (cap); } typedef struct ejour { CharPtr journal_name; Int2 starting_year; } EjourData, PNTR EjourDataPtr; static EjourData mla2_ejour_list [] = { {"Acta Crystallograph. Sect. F Struct. Biol. Cryst. Commun.", 0 }, {"Acta Vet. Scand.", 2006 }, {"Afr. J. Biotechnol.", 0 }, {"Ambul. Surg.", 2005 }, {"Ann. Clin. Microbiol. Antimicrob.", 0 }, {"Appl Plant Sci", 0 }, {"Biol. Direct", 0 }, {"Biotecnol. Apl.", 2002 }, {"BMC Biochem.", 0 }, {"BMC Bioinformatics", 0 }, {"BMC Biotechnol.", 0 }, {"BMC Cancer", 0 }, {"BMC Cell Biol.", 0 }, {"BMC Dermatol.", 0 }, {"BMC Dev. Biol.", 0 }, {"BMC Ecol.", 0 }, {"BMC Evol. Biol.", 0 }, {"BMC Genet.", 0 }, {"BMC Genomics", 0 }, {"BMC Immunol.", 0 }, {"BMC Infect. Dis.", 0 }, {"BMC Med. Genet.", 0 }, {"BMC Microbiol.", 0 }, {"BMC Mol. Biol.", 0 }, {"BMC Pharmacol.", 0 }, {"BMC Physiol.", 0 }, {"BMC Plant Biol.", 0 }, {"BMC Struct. Biol.", 0 }, {"BMC Vet. Res.", 0 }, {"Breast Cancer Res.", 2005 }, {"Cancer Cell Int.", 0 }, {"Cancer Immun.", 0 }, {"Cell Commun. Signal", 0 }, {"Cell Struct. Funct.", 2005 }, {"Cell. Mol. Biol. (Noisy-le-grand)", 2004 }, {"Colomb. Med.", 1998 }, {"Crit. Rev. Oral Biol. Med.", 2002 }, {"Dermatol. Online J.", 0 }, {"Electron. J. Biotechnol.", 0 }, {"Eur. J. Genet. Mol. Toxicol.", 0 }, {"Evol. Bioinform. Online", 0 }, {"Front. Zool.", 0 }, {"Fungal Planet", 0 }, {"Genome Announcements", 0 }, {"Genome Biol.", 2005 }, {"Geochem. Trans.", 0 }, {"Hereditas", 2004 }, {"Hum. Genomics", 2004 }, {"ISRN Genetics", 0 }, {"Infect. Agents Cancer", 0 }, {"J Clin Exp Cardiolog", 0 }, {"J Oral Microbiol", 0 }, {"J. Exp. Clin. Assist. Reprod.", 0 }, {"JOP", 0 }, {"Kinetoplastid Biol Dis", 0 }, {"Malar. J.", 0 }, {"MBio", 0 }, {"Microb. Cell Fact.", 0 }, {"Mol. Syst. Biol.", 0 }, {"Mol. Vis.", 0 }, {"Nat Commun", 0 }, {"Neoplasia", 2005 }, {"Nucl. Recept.", 0 }, {"Pharmacologyonline", 0 }, {"Plant Methods", 0 }, {"PLoS Biol.", 2006 }, {"PLoS Comput. Biol.", 0 }, {"PLoS Genet.", 0 }, {"PLoS Med.", 0 }, {"PLoS Negl Trop Dis", 0 }, {"PLoS ONE", 0 }, {"PLoS Pathog.", 0 }, {"Redox Rep.", 2004 }, {"Reprod. Biol. Endocrinol.", 0 }, {"Retrovirology", 0 }, {"Saline Syst.", 0 }, {"Sci. STKE", 0 }, {"ScientificWorldJournal", 0 }, {"Tech. Tips Online", 0 }, {"Virol. J.", 0 }, {NULL, 0 } }; NLM_EXTERN Boolean Mla2IsEPubOnlyJournal ( CharPtr jta, Int2Ptr starting_yearP ) { EjourDataPtr ejp; Int2 L, R, mid; if (starting_yearP != NULL) { *starting_yearP = 0; } if (StringHasNoText (jta)) return FALSE; L = 0; R = sizeof (mla2_ejour_list) / sizeof (mla2_ejour_list [0]) - 1; /* -1 because now NULL terminated */ while (L < R) { mid = (L + R) / 2; ejp = &(mla2_ejour_list [mid]); if (ejp != NULL && StringICmp (ejp->journal_name, jta) < 0) { L = mid + 1; } else { R = mid; } } ejp = &(mla2_ejour_list [R]); if (ejp != NULL && StringICmp (ejp->journal_name, jta) == 0) { if (starting_yearP != NULL) { *starting_yearP = ejp->starting_year; } return TRUE; } return FALSE; } NLM_EXTERN Int2 Mla2CorrectCitArt ( CitArtPtr newcap, CitArtPtr oldcap ) { if (newcap == NULL) return 0; ChangeCitArtMLAuthorsToSTD (newcap); return 0; }