00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <ncbi_pch.hpp>
00034 #include <objects/taxon1/taxon1.hpp>
00035 #include "cache.hpp"
00036
00037 #include <vector>
00038 #include <algorithm>
00039
00040 BEGIN_NCBI_SCOPE
00041 BEGIN_objects_SCOPE
00042
00043
00044 COrgRefCache::COrgRefCache( CTaxon1& host )
00045 : m_host( host ), m_nCacheCapacity( 10 )
00046 {
00047 return;
00048 }
00049
00050 COrgRefCache::~COrgRefCache()
00051 {
00052 delete[] m_ppEntries;
00053 for( list<SCacheEntry*>::iterator i = m_lCache.begin();
00054 i != m_lCache.end();
00055 ++i ) {
00056 delete *i;
00057 }
00058 }
00059
00060 bool
00061 COrgRefCache::Init( unsigned nCapacity )
00062 {
00063 CTaxon1_req req;
00064 CTaxon1_resp resp;
00065
00066 req.SetMaxtaxid();
00067
00068 if( m_host.SendRequest( req, resp ) ) {
00069 if( resp.IsMaxtaxid() ) {
00070
00071 m_nMaxTaxId = resp.GetMaxtaxid();
00072 m_nMaxTaxId += m_nMaxTaxId/10;
00073 m_ppEntries = new CTaxon1Node*[m_nMaxTaxId];
00074 memset( m_ppEntries, '\0', m_nMaxTaxId*sizeof(*m_ppEntries) );
00075 } else {
00076 m_host.SetLastError( "Response type is not Maxtaxid" );
00077 return false;
00078 }
00079 } else {
00080 return false;
00081 }
00082 CTaxon1_name* pNode = ( new CTaxon1_name );
00083 pNode->SetTaxid( 1 );
00084 pNode->SetOname().assign("root");
00085 pNode->SetCde( 0x40000000 );
00086 CTaxon1Node* pRoot = new CTaxon1Node( CRef<CTaxon1_name>(pNode) );
00087 m_tPartTree.SetRoot( pRoot );
00088 SetIndexEntry( 1, pRoot );
00089
00090 if( nCapacity != 0 ) {
00091 m_nCacheCapacity = nCapacity;
00092 }
00093 InitRanks();
00094 InitDivisions();
00095 return true;
00096 }
00097
00098 bool
00099 COrgRefCache::Lookup( int tax_id, CTaxon1Node** ppNode )
00100 {
00101 if( (unsigned)tax_id < m_nMaxTaxId ) {
00102 *ppNode = m_ppEntries[tax_id];
00103 } else {
00104 *ppNode = NULL;
00105 }
00106 return *ppNode != NULL;
00107 }
00108
00109 bool
00110 COrgRefCache::LookupAndAdd( int tax_id, CTaxon1Node** ppData )
00111 {
00112 *ppData = NULL;
00113 if( (unsigned)tax_id < m_nMaxTaxId ) {
00114 CTaxon1Node* pNode = ( m_ppEntries[tax_id] );
00115 if( pNode ) {
00116 *ppData = pNode;
00117 return true;
00118 } else {
00119 CTaxon1_req req;
00120 CTaxon1_resp resp;
00121
00122 req.SetTaxalineage( tax_id );
00123
00124 if( m_host.SendRequest( req, resp ) ) {
00125 if( resp.IsTaxalineage() ) {
00126
00127 list< CRef<CTaxon1_name> >& lLin = resp.SetTaxalineage();
00128 CTaxon1Node* pParent = 0;
00129 pNode = 0;
00130
00131 if( lLin.front()->GetTaxid() != tax_id ) {
00132
00133 pNode = m_ppEntries[ lLin.front()->GetTaxid() ];
00134 }
00135 if( !pNode ) {
00136 list< CRef< CTaxon1_name > >::reverse_iterator i;
00137
00138 for( i = lLin.rbegin(); i != lLin.rend(); ++i ) {
00139 if( !m_ppEntries[ (*i)->GetTaxid() ] ) {
00140
00141 break;
00142 } else {
00143 pParent = m_ppEntries[ (*i)->GetTaxid() ];
00144 }
00145 }
00146
00147 CTreeIterator* pIt = ( m_tPartTree.GetIterator() );
00148 if( !pParent ) {
00149 pParent = static_cast<CTaxon1Node*>(pIt->GetNode());
00150 }
00151 pIt->GoNode( pParent );
00152 for( ; i != lLin.rend(); ++i ) {
00153 pNode = new CTaxon1Node(*i);
00154 m_ppEntries[ pNode->GetTaxId() ] = pNode;
00155 pIt->AddChild( pNode );
00156 pIt->GoNode( pNode );
00157 }
00158 } else {
00159 m_ppEntries[ tax_id ] = pNode;
00160 }
00161 _ASSERT( pNode );
00162 *ppData = pNode;
00163 return true;
00164 } else {
00165 m_host.SetLastError( "Unable to get node lineage:\
00166 Response type is not Taxalineage" );
00167 return false;
00168 }
00169 }
00170 }
00171 }
00172 return false;
00173 }
00174
00175 bool
00176 COrgRefCache::LookupAndInsert( int tax_id, CTaxon1_data** ppData )
00177 {
00178 CTaxon1Node* pNode = ( NULL );
00179 *ppData = NULL;
00180
00181 if( LookupAndAdd( tax_id, &pNode ) && pNode ) {
00182 SCacheEntry* pEntry = ( pNode->GetEntry() );
00183 if( !pEntry ) {
00184 if( !Insert1( *pNode ) )
00185 return false;
00186 pEntry = pNode->GetEntry();
00187 } else {
00188 m_lCache.remove( pEntry );
00189 m_lCache.push_front( pEntry );
00190 }
00191 *ppData = pEntry->GetData1();
00192 return true;
00193 }
00194 return false;
00195 }
00196
00197 bool
00198 COrgRefCache::LookupAndInsert( int tax_id, CTaxon2_data** ppData )
00199 {
00200 CTaxon1Node* pNode = ( NULL );
00201 *ppData = NULL;
00202
00203 if( LookupAndAdd( tax_id, &pNode ) && pNode ) {
00204 SCacheEntry* pEntry = ( pNode->GetEntry() );
00205 if( !pEntry ) {
00206 if( !Insert2( *pNode ) )
00207 return false;
00208 pEntry = pNode->GetEntry();
00209 } else {
00210 m_lCache.remove( pEntry );
00211 m_lCache.push_front( pEntry );
00212 }
00213 *ppData = pEntry->GetData2();
00214 return true;
00215 }
00216 return false;
00217 }
00218
00219 bool
00220 COrgRefCache::Lookup( int tax_id, CTaxon1_data** ppData )
00221 {
00222 if( (unsigned)tax_id < m_nMaxTaxId ) {
00223 CTaxon1Node* pNode = ( m_ppEntries[tax_id] );
00224 SCacheEntry* pEntry;
00225 if( pNode && (pEntry=pNode->GetEntry()) ) {
00226
00227 m_lCache.remove( pEntry );
00228 m_lCache.push_front( pEntry );
00229 *ppData = pEntry->GetData1();
00230 return true;
00231 }
00232 }
00233 *ppData = NULL;
00234 return false;
00235 }
00236
00237 bool
00238 COrgRefCache::Lookup( int tax_id, CTaxon2_data** ppData )
00239 {
00240 if( (unsigned)tax_id < m_nMaxTaxId ) {
00241 CTaxon1Node* pNode = ( m_ppEntries[tax_id] );
00242 SCacheEntry* pEntry;
00243 if( pNode && (pEntry=pNode->GetEntry()) ) {
00244
00245 m_lCache.remove( pEntry );
00246 m_lCache.push_front( pEntry );
00247 *ppData = pEntry->GetData2();
00248 return true;
00249 }
00250 }
00251 *ppData = NULL;
00252 return false;
00253 }
00254
00255 bool
00256 s_BuildLineage( string& str, CTaxon1Node* pNode, unsigned sz, int sp_rank )
00257 {
00258 if( !pNode->IsRoot() ) {
00259
00260
00261
00262
00263 if( pNode->IsGenBankHidden() ) {
00264 return s_BuildLineage( str, pNode->GetParent(), sz, sp_rank );
00265 }
00266 bool bCont;
00267 bCont=s_BuildLineage( str, pNode->GetParent(),
00268 sz+pNode->GetName().size()+2, sp_rank );
00269 if( bCont ) {
00270 str.append( pNode->GetName() );
00271 if( sz != 0 ) {
00272 str.append( "; " );
00273 }
00274 }
00275 return bCont;
00276
00277 } else {
00278 str.reserve( sz );
00279 }
00280 return true;
00281 }
00282
00283 string::size_type
00284 s_AfterPrefix( const string& str1, const string& prefix )
00285 {
00286 string::size_type pos(0);
00287 if( NStr::StartsWith( str1, prefix ) ) {
00288 pos += prefix.size();
00289 } else {
00290 return string::npos;
00291 }
00292 return str1.find_first_not_of( " \t\n\r", pos );
00293 }
00294
00295 static const char s_achSubsp[] = "subsp.";
00296 static const char s_achSsp[] = "ssp.";
00297 static const char s_achF_Sp[] = "f. sp.";
00298 static const char s_achFSp[] = "f.sp.";
00299 static const char s_achStr[] = "str.";
00300 static const char s_achSubstr[] = "substr.";
00301 static const char s_achVar[] = "var.";
00302 static const char s_achSv[] = "sv.";
00303 static const char s_achCv[] = "cv.";
00304 static const char s_achPv[] = "pv.";
00305 static const char s_achBv[] = "bv.";
00306 static const char s_achF[] = "f.";
00307 static const char s_achFo[] = "fo.";
00308 static const char s_achGrp[] = "grp.";
00309
00310 struct SSubtypeAbbr {
00311 const char* m_pchAbbr;
00312 size_t m_nAbbrLen;
00313 COrgMod::ESubtype m_eSubtype;
00314 };
00315
00316
00317 static SSubtypeAbbr s_aSubtypes[] = {
00318 { s_achSubsp, sizeof(s_achSubsp)-1, COrgMod::eSubtype_sub_species },
00319 { s_achSsp, sizeof(s_achSsp)-1, COrgMod::eSubtype_sub_species },
00320 { s_achF_Sp, sizeof(s_achF_Sp)-1, COrgMod::eSubtype_forma_specialis },
00321 { s_achFSp, sizeof(s_achFSp)-1, COrgMod::eSubtype_forma_specialis },
00322 { s_achStr, sizeof(s_achStr)-1, COrgMod::eSubtype_strain },
00323 { s_achSubstr,sizeof(s_achSubstr)-1,COrgMod::eSubtype_substrain },
00324 { s_achVar, sizeof(s_achVar)-1, COrgMod::eSubtype_variety },
00325 { s_achSv, sizeof(s_achSv)-1, COrgMod::eSubtype_serovar },
00326 { s_achCv, sizeof(s_achCv)-1, COrgMod::eSubtype_cultivar },
00327 { s_achPv, sizeof(s_achPv)-1, COrgMod::eSubtype_pathovar },
00328 { s_achBv, sizeof(s_achBv)-1, COrgMod::eSubtype_biovar },
00329 { s_achF, sizeof(s_achF)-1, COrgMod::eSubtype_forma },
00330 { s_achFo, sizeof(s_achFo)-1, COrgMod::eSubtype_forma },
00331 { s_achGrp, sizeof(s_achGrp)-1, COrgMod::eSubtype_group },
00332 { NULL, 0, COrgMod::eSubtype_other }
00333 };
00334
00335 static int
00336 s_NofTokens( const string& s )
00337 {
00338 int nof = 0;
00339 char first, last, c;
00340 int bracket_level, token;
00341
00342 if( !s.empty() ) {
00343 string::size_type pos = 0;
00344 while( pos < s.size() ) {
00345 bracket_level= 0;
00346 token = 0;
00347
00348 do {
00349 first= s[pos++];
00350 } while( (isspace((unsigned char) first) || iscntrl((unsigned char) first)) &&
00351 pos < s.size() );
00352
00353 switch( first ) {
00354 case '"': last= '"'; break;
00355 case '(': last= ')'; break;
00356 case '{': last= '}'; break;
00357 case '[': last= ']'; break;
00358 default: last= 0; break;
00359 }
00360
00361 for(; pos < s.size(); ++pos) {
00362 c = s[pos];
00363 if( !isalnum((unsigned char) c) ) {
00364 if( last != 0 ) {
00365 if( first == c ) {
00366 ++bracket_level;
00367 }
00368 if( last == c && (!bracket_level--) ) {
00369 ++pos;
00370 break;
00371 }
00372 } else {
00373 if( c == '.' || isspace((unsigned char) c) || iscntrl((unsigned char) c) ) {
00374 ++pos;
00375 break;
00376 }
00377 }
00378 } else {
00379 token = 1;
00380 }
00381 }
00382 nof += token;
00383 }
00384 }
00385 return nof;
00386 }
00387
00388 COrgMod::ESubtype
00389 COrgRefCache::GetSubtypeFromName( string& sName )
00390 {
00391 static const string s_sSubspCf( " subsp. cf." );
00392 static const string s_sSubspAff( " subsp. aff." );
00393 static const string s_sCf( " cf." );
00394 static const string s_sAff( " aff." );
00395
00396 string::size_type pos;
00397 if( sName.find('.') == string::npos ) {
00398 return COrgMod::eSubtype_other;
00399 }
00400
00401 if( NStr::FindNoCase( sName, s_sSubspCf ) != string::npos ) {
00402 return COrgMod::eSubtype_other;
00403 }
00404 if( NStr::FindNoCase( sName, s_sSubspAff ) != string::npos ) {
00405 return COrgMod::eSubtype_other;
00406 }
00407
00408 if( NStr::FindNoCase( sName, s_sCf ) != string::npos ) {
00409 return COrgMod::eSubtype_other;
00410 }
00411 if( NStr::FindNoCase( sName, s_sAff ) != string::npos ) {
00412 return COrgMod::eSubtype_other;
00413 }
00414
00415
00416 SSubtypeAbbr* pSubtypeAbbr = &s_aSubtypes[0];
00417 while( pSubtypeAbbr->m_eSubtype != COrgMod::eSubtype_other ) {
00418 if( (pos=NStr::FindNoCase( sName,
00419 string(pSubtypeAbbr->m_pchAbbr,
00420 pSubtypeAbbr->m_nAbbrLen) )) != NPOS ) {
00421 if( pos == 0 || sName[pos-1] == ' ' || sName[pos-1] == '\t' ) {
00422 sName.erase( pos, pSubtypeAbbr->m_nAbbrLen );
00423 sName = NStr::TruncateSpaces( sName, NStr::eTrunc_Begin );
00424 if( pSubtypeAbbr->m_eSubtype == COrgMod::eSubtype_sub_species
00425 && s_NofTokens( sName ) != 1 ) {
00426 break;
00427 }
00428 return pSubtypeAbbr->m_eSubtype;
00429 }
00430 }
00431 ++pSubtypeAbbr;
00432 }
00433 return COrgMod::eSubtype_other;
00434 }
00435
00436 bool
00437 COrgRefCache::BuildOrgModifier( CTaxon1Node* pNode,
00438 COrgName& on,
00439 CTaxon1Node* pParent )
00440 {
00441 CTaxon1Node* pTmp;
00442 CRef<COrgMod> pMod( new COrgMod );
00443
00444 if( !pParent && !pNode->IsRoot() ) {
00445 pTmp = pNode->GetParent();
00446 while( !pTmp->IsRoot() ) {
00447 int prank = pTmp->GetRank();
00448 if((prank == GetSubspeciesRank()) ||
00449 (prank == GetSpeciesRank()) ||
00450 (prank == GetGenusRank())) {
00451 pParent = pTmp;
00452 break;
00453 }
00454 pTmp = pTmp->GetParent();
00455 }
00456 }
00457 string::size_type pos = 0;
00458 if( pParent ) {
00459 pos = s_AfterPrefix( pNode->GetName(),
00460 pParent->GetName() );
00461 if( pos == string::npos ) {
00462 return false;
00463 }
00464 }
00465 pMod->SetSubname().assign( pNode->GetName(), pos,
00466 pNode->GetName().size()-pos );
00467
00468 pMod->SetSubtype( GetSubtypeFromName( pMod->SetSubname() ) );
00469
00470 if( pMod->GetSubtype() == COrgMod_Base::eSubtype_sub_species &&
00471 (pNode->GetRank() != GetSubspeciesRank() ||
00472 s_NofTokens( pMod->GetSubname() ) != 1) ) {
00473 pMod->SetSubtype( COrgMod_Base::eSubtype_other );
00474 }
00475 if( pMod->GetSubtype() == COrgMod_Base::eSubtype_variety &&
00476 (pNode->GetRank() != GetVarietyRank() ||
00477 s_NofTokens( pMod->GetSubname() ) != 1) ) {
00478 pMod->SetSubtype( COrgMod_Base::eSubtype_other );
00479 }
00480 if( pMod->GetSubtype() == COrgMod_Base::eSubtype_forma &&
00481 (pNode->GetRank() != GetFormaRank() ||
00482 s_NofTokens( pMod->GetSubname() ) != 1) ) {
00483 pMod->SetSubtype( COrgMod_Base::eSubtype_other );
00484 }
00485
00486 if( pMod->GetSubtype() == COrgMod_Base::eSubtype_other ) {
00487 int rank = pNode->GetRank();
00488 if( rank == GetSubspeciesRank() &&
00489 s_NofTokens( pNode->GetName() ) == 3 ) {
00490 pMod->SetSubtype( COrgMod_Base::eSubtype_sub_species );
00491 } else {
00492 return false;
00493 }
00494 }
00495
00496 on.SetMod().push_back( pMod );
00497
00498 return true;
00499 }
00500
00501 bool
00502 COrgRefCache::SetBinomialName( CTaxon1Node& node, COrgName& on )
00503 {
00504 CTaxon1Node* pSpec = ( NULL );
00505 CTaxon1Node* pSubspec = ( NULL );
00506 CTaxon1Node* pGenus = ( NULL );
00507 CTaxon1Node* pSubgen = ( NULL );
00508 CTaxon1Node* pNode = ( &node );
00509 string::size_type pos(0);
00510 do {
00511 int rank( pNode->GetRank() );
00512 if( rank == GetSubspeciesRank())
00513 pSubspec = pNode;
00514 else if( rank == GetSpeciesRank())
00515 pSpec = pNode;
00516 else if( rank == GetSubgenusRank())
00517 pSubgen = pNode;
00518 else if(rank == GetGenusRank()) {
00519 pGenus = pNode;
00520 break;
00521 }
00522 pNode = pNode->GetParent();
00523 } while( pNode && !pNode->IsRoot() );
00524 pNode = &node;
00525
00526 if( !pGenus ) {
00527 if( !pSubgen )
00528 return false;
00529 else
00530 pGenus = pSubgen;
00531 }
00532 CBinomialOrgName& bon = ( on.SetName().SetBinomial() );
00533
00534 bon.SetGenus( pGenus->GetName() );
00535
00536 if( pSpec ) {
00537 pos = s_AfterPrefix( pSpec->GetName(), pGenus->GetName() );
00538 if( pos != string::npos ) {
00539 bon.SetSpecies().assign( pSpec->GetName(),
00540 pos, pSpec->GetName().size() - pos );
00541 } else {
00542 bon.SetSpecies().assign( pSpec->GetName() );
00543 }
00544 if( pSubspec ) {
00545 pos = s_AfterPrefix( pSubspec->GetName(), pSpec->GetName() );
00546 if( pos != string::npos ) {
00547 bon.SetSubspecies().assign( pSubspec->GetName(),
00548 pos,
00549 pSubspec->GetName().size() - pos );
00550 } else {
00551 bon.SetSubspecies().assign( pSubspec->GetName() );
00552 }
00553 }
00554 if( pNode != pSpec ) {
00555 BuildOrgModifier( pNode, on );
00556 }
00557 return true;
00558 }
00559
00560 if( pSubspec ) {
00561 pos = s_AfterPrefix( pSubspec->GetName(), pGenus->GetName() );
00562 if( pos != string::npos ) {
00563 bon.SetSubspecies().assign( pSubspec->GetName(),
00564 pos,
00565 pSubspec->GetName().size() - pos );
00566 } else {
00567 bon.SetSubspecies().assign( pSubspec->GetName() );
00568 }
00569 BuildOrgModifier( pNode, on,
00570 pNode==pSubspec ? pGenus : pSubspec );
00571 return true;
00572 }
00573
00574
00575
00576 BuildOrgModifier( pNode, on, pGenus );
00577 return true;
00578 }
00579
00580 bool
00581 COrgRefCache::SetPartialName( CTaxon1Node& node, COrgName& on )
00582 {
00583 CTaxElement* pTaxElem = ( new CTaxElement );
00584 int rank_id= node.GetRank();
00585
00586 CPartialOrgName& pon = ( on.SetName().SetPartial() );
00587 pon.Set().push_back(CRef<CTaxElement>(pTaxElem));
00588
00589 if( rank_id == GetFamilyRank()) {
00590 pTaxElem->SetFixed_level( CTaxElement_Base::eFixed_level_family );
00591 }
00592 else if(rank_id == GetOrderRank()) {
00593 pTaxElem->SetFixed_level( CTaxElement_Base::eFixed_level_order );
00594 }
00595 else if(rank_id == GetClassRank()) {
00596 pTaxElem->SetFixed_level( CTaxElement_Base::eFixed_level_class );
00597 }
00598 else {
00599 pTaxElem->SetFixed_level( CTaxElement_Base::eFixed_level_other );
00600 pTaxElem->SetLevel( GetRankName( rank_id ) );
00601 }
00602 pTaxElem->SetName( node.GetName() );
00603 return true;
00604 }
00605
00606 bool
00607 COrgRefCache::BuildOrgRef( CTaxon1Node& node, COrg_ref& org, bool& is_species )
00608 {
00609
00610 if( !InitRanks() || !InitNameClasses() || !InitDivisions() )
00611 return false;
00612
00613 CTaxon1_req req;
00614 CTaxon1_resp resp;
00615
00616 req.SetGetorgnames( node.GetTaxId() );
00617
00618 if( m_host.SendRequest( req, resp ) ) {
00619 if( resp.IsGetorgnames() ) {
00620
00621 list< CRef< CTaxon1_name > >&
00622 lLin = ( resp.SetGetorgnames() );
00623
00624 org.SetTaxname().swap( lLin.front()->SetOname() );
00625 lLin.pop_front();
00626
00627 list< CRef< CTaxon1_name > >::iterator i;
00628
00629 int pref_cls = GetPreferredCommonNameClass();
00630 for( i = lLin.begin(); i != lLin.end(); ++i ) {
00631 if( (*i)->CanGetCde() && (*i)->GetCde() == pref_cls ) {
00632 org.SetCommon().swap( (*i)->SetOname() );
00633 lLin.erase( i );
00634 break;
00635 }
00636 }
00637 int syn_cls(GetSynonymNameClass());
00638 int comm_cls(GetCommonNameClass());
00639 for( i = lLin.begin(); i != lLin.end(); ++i ) {
00640 if( (*i)->CanGetCde() ) {
00641 int cls = (*i)->GetCde();
00642 if( cls == syn_cls || cls == comm_cls ) {
00643 org.SetSyn().push_back( (*i)->GetOname() );
00644 }
00645 }
00646 }
00647
00648 org.SetTaxId( node.GetTaxId() );
00649
00650 COrgName& on = ( org.SetOrgname() );
00651
00652 short div_id( node.GetDivision() );
00653 if( GetDivisionCode( div_id ) ) {
00654 on.SetDiv( GetDivisionCode( div_id ) );
00655 }
00656 on.SetGcode( node.GetGC() );
00657 if( node.GetMGC() > 0 ) {
00658 on.SetMgcode( node.GetMGC() );
00659 }
00660
00661 CTaxon1Node* pNode;
00662 if( !node.IsRoot() ) {
00663 pNode = node.GetParent();
00664 on.SetLineage(kEmptyStr);
00665 s_BuildLineage( on.SetLineage(), pNode, 0,
00666 GetSpeciesRank() );
00667 if( on.GetLineage().empty() ) {
00668 on.ResetLineage();
00669 }
00670 }
00671
00672 int rank_id( node.GetRank() );
00673
00674 is_species = (rank_id >= GetSpeciesRank());
00675
00676 if( rank_id < 0 && !node.IsRoot() ) {
00677 pNode = node.GetParent();
00678 while( !pNode->IsRoot() ) {
00679 int rank( pNode->GetRank() );
00680 if(rank >= 0) {
00681 is_species= (rank >= GetSpeciesRank());
00682 break;
00683 }
00684 pNode = pNode->GetParent();
00685 }
00686 }
00687
00688 if(is_species) {
00689
00690
00691
00692 if( div_id == GetVirusesDivision()
00693 || div_id == GetPhagesDivision() ) {
00694
00695
00696 if( rank_id == GetSpeciesRank() ) {
00697
00698 on.SetName().SetVirus( node.GetName() );
00699 } else {
00700
00701
00702
00703 pNode = 0;
00704 CTaxon1Node* pTmp = ( node.GetParent() );
00705
00706 while( pTmp && !pTmp->IsRoot() ) {
00707 int rank(pTmp->GetRank());
00708 if( rank >= GetSpeciesRank() ) {
00709 pNode = pTmp;
00710 if( rank == GetSpeciesRank() )
00711 break;
00712 } else if( rank >= 0 )
00713 break;
00714 pTmp = pTmp->GetParent();
00715 }
00716 if( !pNode ) {
00717 pNode = &node;
00718 }
00719 on.SetName().SetVirus( pNode->GetName() );
00720
00721 BuildOrgModifier( &node, on );
00722 }
00723 } else if( !SetBinomialName( node, on ) ) {
00724
00725 SetPartialName( node, on );
00726 }
00727 } else {
00728 SetPartialName( node, on );
00729 }
00730
00731 if( org.IsSetOrgname() ) {
00732 for( i = lLin.begin(); i != lLin.end(); ++i ) {
00733 if( (*i)->CanGetCde() ) {
00734 int cde = (*i)->GetCde();
00735 COrgMod::ESubtype stype = (COrgMod::ESubtype)0;
00736 if( cde == GetGBAcronymNameClass() ) {
00737 stype = COrgMod::eSubtype_gb_acronym;
00738 } else if( cde == GetGBSynonymNameClass() ) {
00739 stype = COrgMod::eSubtype_gb_synonym;
00740 } else if( cde == GetGBAnamorphNameClass() ) {
00741 stype = COrgMod::eSubtype_gb_anamorph;
00742 }
00743 if( stype ) {
00744 CRef<COrgMod> pMod( new COrgMod );
00745 pMod->SetSubname().swap( (*i)->SetOname() );
00746 pMod->SetSubtype( stype );
00747 on.SetMod().push_back( pMod );
00748 }
00749 }
00750 }
00751 }
00752
00753 } else {
00754 m_host.SetLastError
00755 ("Unable to get orgref: Response is not Getorgnames");
00756 return false;
00757 }
00758 } else
00759 return false;
00760 return true;
00761 }
00762
00763 bool
00764 COrgRefCache::Insert1( CTaxon1Node& node )
00765 {
00766 bool is_species( false );
00767 struct SCacheEntry* pEntry = ( new SCacheEntry );
00768 pEntry->m_pTax1 = new CTaxon1_data;
00769 pEntry->m_pTax2 = NULL;
00770 pEntry->m_pTreeNode = &node;
00771
00772 COrg_ref& org = ( pEntry->m_pTax1->SetOrg() );
00773
00774 if( !BuildOrgRef( node, org, is_species ) ) {
00775 delete pEntry;
00776 return false;
00777 }
00778
00779 if( GetDivisionCode(node.GetDivision()) ) {
00780 pEntry->m_pTax1->SetDiv()
00781 .assign( GetDivisionCode(node.GetDivision()) );
00782 }
00783
00784 pEntry->m_pTax1->SetIs_species_level( is_species );
00785
00786 if( m_lCache.size() >= m_nCacheCapacity ) {
00787 CTaxon1Node* pNode = ( m_lCache.back()->m_pTreeNode );
00788 pNode->m_cacheEntry = NULL;
00789 delete m_lCache.back();
00790 m_lCache.pop_back();
00791 }
00792
00793 node.m_cacheEntry = pEntry;
00794 m_lCache.push_front( pEntry );
00795
00796 return true;
00797 }
00798
00799 bool
00800 COrgRefCache::Insert2( CTaxon1Node& node )
00801 {
00802 bool is_species( false );
00803 struct SCacheEntry* pEntry = ( new SCacheEntry );
00804 pEntry->m_pTax1 = NULL;
00805 pEntry->m_pTax2 = new CTaxon2_data;
00806 pEntry->m_pTreeNode = &node;
00807
00808 pEntry->m_pTax2->SetIs_uncultured( node.IsUncultured() );
00809
00810 COrg_ref& org = pEntry->m_pTax2->SetOrg();
00811
00812 if( !BuildOrgRef( node, org, is_species ) ) {
00813 delete pEntry;
00814 return false;
00815 }
00816
00817 CTaxon1Node* pNode = ( &node );
00818 while( !pNode->IsRoot() ) {
00819 if( !pNode->GetBlastName().empty() ) {
00820 pEntry->m_pTax2->SetBlast_name()
00821 .push_back( pNode->GetBlastName() );
00822 }
00823 pNode = pNode->GetParent();
00824 }
00825
00826 pEntry->m_pTax2->SetIs_species_level( is_species );
00827
00828 if( m_lCache.size() >= m_nCacheCapacity ) {
00829 pNode = m_lCache.back()->m_pTreeNode;
00830 pNode->m_cacheEntry = NULL;
00831 delete m_lCache.back();
00832 m_lCache.pop_back();
00833 }
00834
00835 node.m_cacheEntry = pEntry;
00836 m_lCache.push_front( pEntry );
00837
00838 return true;
00839 }
00840
00841 CTaxon1_data*
00842 COrgRefCache::SCacheEntry::GetData1()
00843 {
00844 if( ! m_pTax1 ) {
00845 m_pTax1 = new CTaxon1_data;
00846 if( m_pTax2->IsSetOrg() ) {
00847 m_pTax1->SetOrg( m_pTax2->SetOrg() );
00848 }
00849 if( m_pTax2->GetOrg().GetOrgname().CanGetDiv() ) {
00850 m_pTax1->SetDiv( m_pTax2->GetOrg().GetOrgname().GetDiv() );
00851 } else {
00852 m_pTax1->SetDiv( kEmptyStr );
00853 }
00854 m_pTax1->SetIs_species_level(m_pTax2->GetIs_species_level());
00855 }
00856 return m_pTax1;
00857 }
00858
00859 CTaxon2_data*
00860 COrgRefCache::SCacheEntry::GetData2()
00861 {
00862 if( ! m_pTax2 ) {
00863 m_pTax2 = new CTaxon2_data;
00864 if( m_pTax1->IsSetOrg() ) {
00865 m_pTax2->SetOrg( m_pTax1->SetOrg() );
00866 }
00867 CTaxon1Node* pNode = ( m_pTreeNode );
00868 while( !pNode->IsRoot() ) {
00869 if( !pNode->GetBlastName().empty() ) {
00870 m_pTax2->SetBlast_name().push_back( pNode->GetBlastName() );
00871 }
00872 pNode = pNode->GetParent();
00873 }
00874 m_pTax2->SetIs_uncultured( m_pTreeNode->IsUncultured() );
00875 m_pTax2->SetIs_species_level(m_pTax1->GetIs_species_level());
00876 }
00877 return m_pTax2;
00878 }
00879
00880 int
00881 COrgRefCache::FindRankByName( const char* pchName ) const
00882 {
00883 for( TRankMapCI ci = m_rankStorage.begin();
00884 ci != m_rankStorage.end();
00885 ++ci )
00886 if( ci->second.compare( pchName ) == 0 )
00887 return ci->first;
00888 return -1000;
00889 }
00890
00891
00892 const char*
00893 COrgRefCache::GetRankName( int rank ) const
00894 {
00895 TRankMapCI ci( m_rankStorage.find( rank ) );
00896 if( ci != m_rankStorage.end() ) {
00897 return ci->second.c_str();
00898 }
00899 return NULL;
00900 }
00901
00902 bool
00903 COrgRefCache::InitRanks()
00904 {
00905 if( m_rankStorage.size() == 0 ) {
00906
00907 CTaxon1_req req;
00908 CTaxon1_resp resp;
00909
00910 req.SetGetranks();
00911
00912 if( m_host.SendRequest( req, resp ) ) {
00913 if( resp.IsGetranks() ) {
00914
00915 const list< CRef< CTaxon1_info > >&
00916 lRanks = ( resp.GetGetranks() );
00917
00918 for( list< CRef< CTaxon1_info > >::const_iterator
00919 i = lRanks.begin();
00920 i != lRanks.end(); ++i ) {
00921 m_rankStorage
00922 .insert( TRankMap::value_type((*i)->GetIval1(),
00923 (*i)->GetSval()) );
00924 }
00925 } else {
00926 m_host.SetLastError( "Response type is not Getranks" );
00927 return false;
00928 }
00929 }
00930
00931 m_nSuperkingdomRank = FindRankByName( "superkingdom" );
00932 if( m_nSuperkingdomRank < -10 ) {
00933 m_host.SetLastError( "Superkingdom rank was not found" );
00934 return false;
00935 }
00936 m_nFamilyRank = FindRankByName( "family" );
00937 if( m_nFamilyRank < -10 ) {
00938 m_host.SetLastError( "Family rank was not found" );
00939 return false;
00940 }
00941 m_nOrderRank = FindRankByName( "order" );
00942 if( m_nOrderRank < -10 ) {
00943 m_host.SetLastError( "Order rank was not found" );
00944 return false;
00945 }
00946 m_nClassRank = FindRankByName( "class" );
00947 if( m_nClassRank < -10 ) {
00948 m_host.SetLastError( "Class rank was not found" );
00949 return false;
00950 }
00951 m_nGenusRank = FindRankByName( "genus" );
00952 if( m_nGenusRank < -10 ) {
00953 m_host.SetLastError( "Genus rank was not found" );
00954 return false;
00955 }
00956 m_nSubgenusRank = FindRankByName( "subgenus" );
00957 if( m_nSubgenusRank < -10 ) {
00958 m_host.SetLastError( "Subgenus rank was not found" );
00959 return false;
00960 }
00961 m_nSpeciesRank = FindRankByName( "species" );
00962 if( m_nSpeciesRank < -10 ) {
00963 m_host.SetLastError( "Species rank was not found" );
00964 return false;
00965 }
00966 m_nSubspeciesRank = FindRankByName( "subspecies" );
00967 if( m_nSubspeciesRank < -10 ) {
00968 m_host.SetLastError( "Subspecies rank was not found" );
00969 return false;
00970 }
00971 m_nFormaRank = FindRankByName( "forma" );
00972 if( m_nFormaRank < -10 ) {
00973 m_host.SetLastError( "Forma rank was not found" );
00974 return false;
00975 }
00976 m_nVarietyRank = FindRankByName( "varietas" );
00977 if( m_nVarietyRank < -10 ) {
00978 m_host.SetLastError( "Variety rank was not found" );
00979 return false;
00980 }
00981 }
00982 return true;
00983 }
00984
00985 const char*
00986 COrgRefCache::GetNameClassName( short nc ) const
00987 {
00988 TNameClassMapCI ci( m_ncStorage.find( nc ) );
00989 if( ci != m_ncStorage.end() ) {
00990 return ci->second.c_str();
00991 }
00992 return NULL;
00993 }
00994
00995 short
00996 COrgRefCache::FindNameClassByName( const char* pchName ) const
00997 {
00998 for( TNameClassMapCI ci = m_ncStorage.begin();
00999 ci != m_ncStorage.end();
01000 ++ci )
01001 if( ci->second.compare( pchName ) == 0 )
01002 return ci->first;
01003 return -1;
01004 }
01005
01006 bool
01007 COrgRefCache::InitNameClasses()
01008 {
01009 if( m_ncStorage.size() == 0 ) {
01010
01011 CTaxon1_req req;
01012 CTaxon1_resp resp;
01013
01014 req.SetGetcde();
01015
01016 if( m_host.SendRequest( req, resp ) ) {
01017 if( resp.IsGetcde() ) {
01018
01019 const list< CRef< CTaxon1_info > >&
01020 l = ( resp.GetGetcde() );
01021
01022 for( list< CRef< CTaxon1_info > >::const_iterator
01023 i = l.begin();
01024 i != l.end(); ++i )
01025 m_ncStorage
01026 .insert( TNameClassMap::value_type((*i)->GetIval1(),
01027 (*i)->GetSval()) );
01028 } else {
01029 m_host.SetLastError( "Response type is not Getcde" );
01030 return false;
01031 }
01032 }
01033
01034 m_ncPrefCommon = FindNameClassByName( "genbank common name" );
01035 if( m_ncPrefCommon < 0 ) {
01036 m_host.SetLastError( "Genbank common name class was not found" );
01037 return false;
01038 }
01039 m_ncCommon = FindNameClassByName( "common name" );
01040 if( m_ncCommon < 0 ) {
01041 m_host.SetLastError( "Common name class was not found" );
01042 return false;
01043 }
01044 m_ncSynonym = FindNameClassByName( "synonym" );
01045 if( m_ncSynonym < 0 ) {
01046 m_host.SetLastError( "Synonym name class was not found" );
01047 return false;
01048 }
01049
01050 m_ncGBAcronym= FindNameClassByName("genbank acronym");
01051 if( m_ncGBAcronym < 0 ) {
01052 m_host.SetLastError( "Genbank acrony name class was not found" );
01053 return false;
01054 }
01055 m_ncGBSynonym= FindNameClassByName("genbank synonym");
01056 if( m_ncGBSynonym < 0 ) {
01057 m_host.SetLastError( "Genbank synonym name class was not found" );
01058 return false;
01059 }
01060 m_ncGBAnamorph= FindNameClassByName("genbank anamorph");
01061 if( m_ncGBAnamorph < 0 ) {
01062 m_host.SetLastError( "Genbank anamorph name class was not found" );
01063 return false;
01064 }
01065 }
01066 return true;
01067 }
01068
01069 short
01070 COrgRefCache::FindDivisionByCode( const char* pchCode ) const
01071 {
01072 for( TDivisionMapCI ci = m_divStorage.begin();
01073 ci != m_divStorage.end();
01074 ++ci ) {
01075 const char* cp = ( ci->second.m_sCode.c_str() );
01076 if( strcmp( cp, pchCode ) == 0 )
01077 return ci->first;
01078 }
01079 return -1;
01080 }
01081
01082
01083 const char*
01084 COrgRefCache::GetDivisionCode( short div_id ) const
01085 {
01086 TDivisionMapCI ci( m_divStorage.find( div_id ) );
01087 if( ci != m_divStorage.end() ) {
01088 return ci->second.m_sCode.c_str();
01089 }
01090 return NULL;
01091 }
01092
01093 const char*
01094 COrgRefCache::GetDivisionName( short div_id ) const
01095 {
01096 TDivisionMapCI ci( m_divStorage.find( div_id ) );
01097 if( ci != m_divStorage.end() ) {
01098 return ci->second.m_sName.c_str();
01099 }
01100 return NULL;
01101 }
01102
01103
01104 bool
01105 COrgRefCache::InitDivisions()
01106 {
01107 if( m_divStorage.size() == 0 ) {
01108
01109 CTaxon1_req req;
01110 CTaxon1_resp resp;
01111
01112 req.SetGetdivs();
01113
01114 if( m_host.SendRequest( req, resp ) ) {
01115 if( resp.IsGetdivs() ) {
01116
01117 const list< CRef< CTaxon1_info > >&
01118 l = ( resp.GetGetdivs() );
01119
01120 for( list< CRef< CTaxon1_info > >::const_iterator
01121 i = l.begin();
01122 i != l.end(); ++i ) {
01123 SDivision& div = ( m_divStorage[(*i)->GetIval1()] );
01124 div.m_sName.assign( (*i)->GetSval() );
01125 int code = (*i)->GetIval2();
01126 for(int k= 0; k < 3; k++) {
01127 div.m_sCode.append( 1U, (code >> (8*(3-k))) & 0xFF );
01128 }
01129 div.m_sCode.append( 1U, code & 0xFF );
01130 }
01131 } else {
01132 m_host.SetLastError( "Response type is not Getdivs" );
01133 return false;
01134 }
01135 }
01136
01137 if( (m_divViruses = FindDivisionByCode( "VRL" )) < 0 ) {
01138 m_host.SetLastError( "Viruses division was not found" );
01139 return false;
01140 }
01141 if( (m_divPhages = FindDivisionByCode( "PHG" )) < 0 ) {
01142 m_host.SetLastError( "Phages division was not found" );
01143 return false;
01144 }
01145 }
01146 return true;
01147 }
01148
01149 void
01150 COrgRefCache::SetIndexEntry( int id, CTaxon1Node* pNode )
01151 {
01152 m_ppEntries[id] = pNode;
01153 }
01154
01155
01156
01157
01158
01159 bool
01160 CTaxTreeConstIterator::IsLastChild() const
01161 {
01162 const CTreeContNodeBase* pOldNode = m_it->GetNode();
01163 bool bResult = true;
01164
01165 while( m_it->GoParent() ) {
01166 if( IsVisible( m_it->GetNode() ) ) {
01167 const CTreeContNodeBase* pParent = m_it->GetNode();
01168 m_it->GoNode( pOldNode );
01169 while( m_it->GetNode() != pParent ) {
01170 if( m_it->GoSibling() ) {
01171 bResult = !NextVisible( pParent );
01172 break;
01173 }
01174 if( !m_it->GoParent() ) {
01175 break;
01176 }
01177 }
01178 break;
01179 }
01180 }
01181 m_it->GoNode( pOldNode );
01182 return bResult;
01183 }
01184
01185 bool
01186 CTaxTreeConstIterator::IsFirstChild() const
01187 {
01188 const CTreeContNodeBase* pOldNode = m_it->GetNode();
01189 bool bResult = false;
01190
01191 while( m_it->GoParent() ) {
01192 if( IsVisible( m_it->GetNode() ) ) {
01193 const CTreeContNodeBase* pParent = m_it->GetNode();
01194 if( m_it->GoChild() ) {
01195 bResult = NextVisible(pParent) && m_it->GetNode() == pOldNode;
01196 }
01197 break;
01198 }
01199 }
01200 m_it->GoNode( pOldNode );
01201 return bResult;
01202 }
01203
01204 bool
01205 CTaxTreeConstIterator::IsTerminal() const
01206 {
01207 const CTreeContNodeBase* pOldNode = m_it->GetNode();
01208
01209 if( m_it->GoChild() ) {
01210 bool bResult = NextVisible( pOldNode );
01211 m_it->GoNode( pOldNode );
01212 return !bResult;
01213 }
01214 return true;
01215 }
01216
01217 bool
01218 CTaxTreeConstIterator::NextVisible( const CTreeContNodeBase* pParent ) const
01219 {
01220 if( m_it->GetNode() == pParent ) {
01221 return false;
01222 }
01223 next:
01224 if( IsVisible( m_it->GetNode() ) ) {
01225 return true;
01226 }
01227 if( m_it->GoChild() ) {
01228 goto next;
01229 } else if( m_it->GoSibling() ) {
01230 goto next;
01231 } else {
01232 while( m_it->GoParent() && m_it->GetNode() != pParent ) {
01233 if( m_it->GoSibling() ) {
01234 goto next;
01235 }
01236 }
01237 }
01238 return false;
01239 }
01240
01241 bool
01242 CTaxTreeConstIterator::GoParent()
01243 {
01244 const CTreeContNodeBase* pOldNode = m_it->GetNode();
01245 bool bResult = false;
01246 while( m_it->GoParent() ) {
01247 if( IsVisible( m_it->GetNode() ) ) {
01248 bResult = true;
01249 break;
01250 }
01251 }
01252 if( !bResult ) {
01253 m_it->GoNode( pOldNode );
01254 }
01255 return bResult;
01256 }
01257
01258 bool
01259 CTaxTreeConstIterator::GoChild()
01260 {
01261 const CTreeContNodeBase* pOldNode = m_it->GetNode();
01262 bool bResult = false;
01263
01264 if( m_it->GoChild() ) {
01265 bResult = NextVisible( pOldNode );
01266 }
01267 if( !bResult ) {
01268 m_it->GoNode( pOldNode );
01269 }
01270 return bResult;
01271 }
01272
01273 bool
01274 CTaxTreeConstIterator::GoSibling()
01275 {
01276 const CTreeContNodeBase* pOldNode = m_it->GetNode();
01277 bool bResult = false;
01278
01279 if( GoParent() ) {
01280 const CTreeContNodeBase* pParent = m_it->GetNode();
01281 m_it->GoNode( pOldNode );
01282 while( m_it->GetNode() != pParent ) {
01283 if( m_it->GoSibling() ) {
01284 bResult = NextVisible( pParent );
01285 break;
01286 }
01287 if( !m_it->GoParent() ) {
01288 break;
01289 }
01290 }
01291 if( !bResult ) {
01292 m_it->GoNode( pOldNode );
01293 }
01294 }
01295 return bResult;
01296 }
01297
01298 bool
01299 CTaxTreeConstIterator::GoNode( const ITaxon1Node* pNode )
01300 {
01301 const CTreeContNodeBase* pTaxNode = CastIC( pNode );
01302
01303 if( pNode && IsVisible( pTaxNode ) ) {
01304 return m_it->GoNode( pTaxNode );
01305 }
01306 return false;
01307 }
01308
01309 bool
01310 CTaxTreeConstIterator::GoAncestor(const ITaxon1Node* pINode)
01311 {
01312 const CTreeContNodeBase* pNode = CastIC( pINode );
01313 if( pNode && IsVisible( pNode ) ) {
01314 const CTreeContNodeBase* pOldNode = m_it->GetNode();
01315
01316 vector< const CTreeContNodeBase* > v;
01317 do {
01318 v.push_back( m_it->GetNode() );
01319 } while( GoParent() );
01320
01321 m_it->GoNode( pNode );
01322 vector< const CTreeContNodeBase* >::const_iterator vi;
01323 do {
01324 vi = find( v.begin(), v.end(), m_it->GetNode() );
01325 if( vi != v.end() ) {
01326 return true;
01327 }
01328 } while( GoParent() );
01329
01330 m_it->GoNode( pOldNode );
01331 }
01332 return false;
01333 }
01334
01335 bool
01336 CTaxTreeConstIterator::BelongSubtree(const ITaxon1Node* pIRoot) const
01337 {
01338 const CTreeContNodeBase* pRoot = CastIC( pIRoot );
01339 if( pRoot && IsVisible( pRoot ) ) {
01340 const CTreeContNodeBase* pOldNode = m_it->GetNode();
01341 do {
01342 if( IsVisible( m_it->GetNode() ) ) {
01343 if( m_it->GetNode() == pRoot ) {
01344 m_it->GoNode( pOldNode );
01345 return true;
01346 }
01347 }
01348 } while( m_it->GoParent() );
01349 m_it->GoNode( pOldNode );
01350 }
01351 return false;
01352 }
01353
01354
01355 bool
01356 CTaxTreeConstIterator::AboveNode(const ITaxon1Node* pINode) const
01357 {
01358 const CTreeContNodeBase* pNode = CastIC( pINode );
01359 if( pNode == m_it->GetNode() ) {
01360 return false;
01361 }
01362
01363 if( pNode && IsVisible( pNode ) ) {
01364 const CTreeContNodeBase* pOldNode = m_it->GetNode();
01365 m_it->GoNode( pNode );
01366 do {
01367 if( IsVisible( m_it->GetNode() ) ) {
01368 if( m_it->GetNode() == pOldNode ) {
01369 m_it->GoNode( pOldNode );
01370 return true;
01371 }
01372 }
01373 } while( m_it->GoParent() );
01374 m_it->GoNode( pOldNode );
01375 }
01376 return false;
01377 }
01378
01379 bool
01380 CTreeLeavesBranchesIterator::IsVisible( const CTreeContNodeBase* pNode ) const
01381 {
01382 return pNode &&
01383 ( pNode->IsRoot() || pNode->IsTerminal() ||
01384 !pNode->Child()->IsLastChild() );
01385 }
01386
01387 bool
01388 CTreeBestIterator::IsVisible( const CTreeContNodeBase* pNode ) const
01389 {
01390 return pNode &&
01391 ( pNode->IsRoot() || pNode->IsTerminal() ||
01392 !pNode->Child()->IsLastChild() ||
01393 !(pNode->IsLastChild() && pNode->IsFirstChild()) );
01394
01395 }
01396
01397 bool
01398 CTreeBlastIterator::IsVisible( const CTreeContNodeBase* pNode ) const
01399 {
01400 return pNode && ( pNode->IsRoot() ||
01401 !CastCI(pNode)->GetBlastName().empty() );
01402 }
01403
01404
01405 END_objects_SCOPE
01406 END_NCBI_SCOPE
01407
01408