cache.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:42k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: cache.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:35:08  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.21
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: cache.cpp,v 1000.3 2004/06/01 19:35:08 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Vladimir Soussov, Michael Domrachev
  35.  *
  36.  * File Description:
  37.  *     NCBI Taxonomy information retreival library caching implementation
  38.  *
  39.  */
  40. #include <ncbi_pch.hpp>
  41. #include <objects/taxon1/taxon1.hpp>
  42. #include "cache.hpp"
  43. #include <vector>
  44. #include <algorithm>
  45. BEGIN_NCBI_SCOPE
  46. BEGIN_objects_SCOPE
  47. COrgRefCache::COrgRefCache( CTaxon1& host )
  48.     : m_host( host ), m_nCacheCapacity( 10 )
  49. {
  50.     return;
  51. }
  52. bool
  53. COrgRefCache::Init( unsigned nCapacity )
  54. {
  55.     CTaxon1_req  req;
  56.     CTaxon1_resp resp;
  57.     req.SetMaxtaxid();
  58.     if( m_host.SendRequest( req, resp ) ) {
  59.         if( resp.IsMaxtaxid() ) {
  60.             // Correct response, return object
  61.             m_nMaxTaxId = resp.GetMaxtaxid();
  62.             m_nMaxTaxId += m_nMaxTaxId/10;
  63.             m_ppEntries = new CTaxon1Node*[m_nMaxTaxId];
  64.             memset( m_ppEntries, '', m_nMaxTaxId*sizeof(*m_ppEntries) );
  65.         } else { // Internal: wrong respond type
  66.             m_host.SetLastError( "Response type is not Maxtaxid" );
  67.             return false;
  68.         }
  69.     } else {
  70.         return false;
  71.     }
  72.     CTaxon1_name* pNode = ( new CTaxon1_name );
  73.     pNode->SetTaxid( 1 );
  74.     pNode->SetOname().assign("root");
  75.     pNode->SetCde( 0x40000000 ); // Gene bank hidden
  76.     CTaxon1Node* pRoot = new CTaxon1Node( CRef<CTaxon1_name>(pNode) );
  77.     m_tPartTree.SetRoot( pRoot );
  78.     SetIndexEntry( 1, pRoot );
  79.     if( nCapacity != 0 ) {
  80. m_nCacheCapacity = nCapacity;
  81.     }
  82.     InitRanks();
  83.     InitDivisions();
  84.     return true;
  85. }
  86. bool
  87. COrgRefCache::Lookup( int tax_id, CTaxon1Node** ppNode )
  88. {
  89.     if( (unsigned)tax_id < m_nMaxTaxId ) {
  90.         *ppNode = m_ppEntries[tax_id];
  91.     } else {
  92. *ppNode = NULL;
  93.     }
  94.     return *ppNode != NULL;
  95. }
  96. bool
  97. COrgRefCache::LookupAndAdd( int tax_id, CTaxon1Node** ppData )
  98. {
  99.     *ppData = NULL;
  100.     if( (unsigned)tax_id < m_nMaxTaxId ) {
  101.         CTaxon1Node* pNode = ( m_ppEntries[tax_id] );
  102.         if( pNode ) {
  103.             *ppData = pNode;
  104.             return true;
  105.         } else { // Add the entry from server
  106.             CTaxon1_req  req;
  107.             CTaxon1_resp resp;
  108.             req.SetTaxalineage( tax_id );
  109.             if( m_host.SendRequest( req, resp ) ) {
  110.                 if( resp.IsTaxalineage() ) {
  111.                     // Correct response, return object
  112.                     list< CRef<CTaxon1_name> >& lLin = resp.SetTaxalineage();
  113.                     CTaxon1Node* pParent = 0;
  114.                     pNode   = 0;
  115.     // Check if this is a secondary node
  116.     if( lLin.front()->GetTaxid() != tax_id ) {
  117. // Secondary node, try to get primary from index
  118. pNode = m_ppEntries[ lLin.front()->GetTaxid() ];
  119.     }
  120.     if( !pNode ) {
  121. list< CRef< CTaxon1_name > >::reverse_iterator i;
  122. // Fill in storage
  123. for( i = lLin.rbegin(); i != lLin.rend(); ++i ) {
  124.     if( !m_ppEntries[ (*i)->GetTaxid() ] ) {
  125. // Create node
  126. break;
  127.     } else {
  128. pParent = m_ppEntries[ (*i)->GetTaxid() ];
  129.     }
  130. }
  131. // Create tree iterator
  132. CTreeIterator* pIt = ( m_tPartTree.GetIterator() );
  133. if( !pParent ) {
  134.     pParent = static_cast<CTaxon1Node*>(pIt->GetNode());
  135. }
  136. pIt->GoNode( pParent );
  137. for( ; i != lLin.rend(); ++i ) {
  138.     pNode = new CTaxon1Node(*i);
  139.     m_ppEntries[ pNode->GetTaxId() ] = pNode;
  140.     pIt->AddChild( pNode );
  141.     pIt->GoNode( pNode );
  142. }
  143.     } else { // Store secondary in index
  144. m_ppEntries[ tax_id ] = pNode;
  145.     }
  146.     _ASSERT( pNode );
  147.                     *ppData = pNode;
  148.                     return true;
  149.                 } else { // Internal: wrong respond type
  150.                     m_host.SetLastError( "Unable to get node lineage:
  151.  Response type is not Taxalineage" );
  152.                     return false;
  153.                 }
  154.             }
  155.         }
  156.     }
  157.     return false;
  158. }
  159. bool
  160. COrgRefCache::LookupAndInsert( int tax_id, CTaxon1_data** ppData )
  161. {
  162.     CTaxon1Node* pNode = ( NULL );
  163.     *ppData = NULL;
  164.     if( LookupAndAdd( tax_id, &pNode ) && pNode ) {
  165.         SCacheEntry* pEntry = ( pNode->GetEntry() );
  166.         if( !pEntry ) {
  167.             if( !Insert1( *pNode ) )
  168.                 return false;
  169.             pEntry = pNode->GetEntry();
  170.         } else {
  171.             m_lCache.remove( pEntry );
  172.             m_lCache.push_front( pEntry );
  173.         }
  174.         *ppData = pEntry->GetData1();
  175.         return true;
  176.     }
  177.     return false;
  178. }
  179. bool
  180. COrgRefCache::LookupAndInsert( int tax_id, CTaxon2_data** ppData )
  181. {
  182.     CTaxon1Node* pNode = ( NULL );
  183.     *ppData = NULL;
  184.     if( LookupAndAdd( tax_id, &pNode ) && pNode ) {
  185.         SCacheEntry* pEntry = ( pNode->GetEntry() );
  186.         if( !pEntry ) {
  187.             if( !Insert2( *pNode ) )
  188.                 return false;
  189.             pEntry = pNode->GetEntry();
  190.         } else {
  191.             m_lCache.remove( pEntry );
  192.             m_lCache.push_front( pEntry );
  193.         }
  194.         *ppData = pEntry->GetData2();
  195.         return true;
  196.     }
  197.     return false;
  198. }
  199. bool
  200. COrgRefCache::Lookup( int tax_id, CTaxon1_data** ppData )
  201. {
  202.     if( (unsigned)tax_id < m_nMaxTaxId ) {
  203.         CTaxon1Node* pNode = ( m_ppEntries[tax_id] );
  204.         SCacheEntry* pEntry;
  205.         if( pNode && (pEntry=pNode->GetEntry()) ) {
  206.             // Move in the list
  207.             m_lCache.remove( pEntry );
  208.             m_lCache.push_front( pEntry );
  209.             *ppData = pEntry->GetData1();
  210.             return true;
  211.         }
  212.     }
  213.     *ppData = NULL;
  214.     return false;
  215. }
  216. bool
  217. COrgRefCache::Lookup( int tax_id, CTaxon2_data** ppData )
  218. {
  219.     if( (unsigned)tax_id < m_nMaxTaxId ) {
  220.         CTaxon1Node* pNode = ( m_ppEntries[tax_id] );
  221.         SCacheEntry* pEntry;
  222.         if( pNode && (pEntry=pNode->GetEntry()) ) {
  223.             // Move in the list
  224.             m_lCache.remove( pEntry );
  225.             m_lCache.push_front( pEntry );
  226.             *ppData = pEntry->GetData2();
  227.             return true;
  228.         }
  229.     }
  230.     *ppData = NULL;
  231.     return false;
  232. }
  233. bool
  234. s_BuildLineage( string& str, CTaxon1Node* pNode, unsigned sz, int sp_rank )
  235. {
  236.     if( !pNode->IsRoot() ) {
  237.         if( pNode->GetRank() > sp_rank-1 ) {
  238.             s_BuildLineage( str, pNode->GetParent(), 0, sp_rank );
  239.             return false;
  240.         } else {
  241.             if( pNode->IsGenBankHidden() ) {
  242.                 return s_BuildLineage( str, pNode->GetParent(), sz, sp_rank );
  243.             }
  244.             bool bCont;
  245.             bCont=s_BuildLineage( str, pNode->GetParent(),
  246.                                   sz+pNode->GetName().size()+2, sp_rank );
  247.             if( bCont ) {
  248.                 str.append( pNode->GetName() );
  249. if( sz != 0 ) {
  250.     str.append( "; " );
  251. }
  252.             }
  253.             return bCont;
  254.         }
  255.     } else {
  256.         str.reserve( sz );
  257.     }
  258.     return true;
  259. }
  260. string::size_type
  261. s_AfterPrefix( const string& str1, const string& prefix )
  262. {
  263.     string::size_type pos(0);
  264.     if( NStr::StartsWith( str1, prefix ) ) {
  265.         pos += prefix.size();
  266.     }
  267.     return str1.find_first_not_of( " tnr", pos );
  268. }
  269. static const char s_achSubsp[] = "subsp.";
  270. static const char s_achSsp[] = "ssp.";
  271. static const char s_achF_Sp[] = "f. sp.";
  272. static const char s_achFSp[] = "f.sp.";
  273. static const char s_achStr[] = "str.";
  274. static const char s_achSubstr[] = "substr.";
  275. static const char s_achVar[] = "var.";
  276. static const char s_achSv[] = "sv.";
  277. static const char s_achCv[] = "cv.";
  278. static const char s_achPv[] = "pv.";
  279. static const char s_achBv[] = "bv.";
  280. static const char s_achF[] = "f.";
  281. static const char s_achFo[] = "fo.";
  282. static const char s_achGrp[] = "grp.";
  283. struct SSubtypeAbbr {
  284.     const char*       m_pchAbbr;
  285.     size_t            m_nAbbrLen;
  286.     COrgMod::ESubtype m_eSubtype;
  287. };
  288. static SSubtypeAbbr s_aSubtypes[] = {
  289.     { s_achSubsp, sizeof(s_achSubsp)-1, COrgMod::eSubtype_sub_species },
  290.     { s_achSsp,   sizeof(s_achSsp)-1,   COrgMod::eSubtype_sub_species },
  291.     { s_achF_Sp,  sizeof(s_achF_Sp)-1,  COrgMod::eSubtype_forma_specialis },
  292.     { s_achFSp,   sizeof(s_achFSp)-1,   COrgMod::eSubtype_forma_specialis },
  293.     { s_achStr,   sizeof(s_achStr)-1,   COrgMod::eSubtype_strain },
  294.     { s_achSubstr,sizeof(s_achSubstr)-1,COrgMod::eSubtype_substrain },
  295.     { s_achVar,   sizeof(s_achVar)-1,   COrgMod::eSubtype_variety },
  296.     { s_achSv,    sizeof(s_achSv)-1,    COrgMod::eSubtype_serovar },
  297.     { s_achCv,    sizeof(s_achCv)-1,    COrgMod::eSubtype_cultivar },
  298.     { s_achPv,    sizeof(s_achPv)-1,    COrgMod::eSubtype_pathovar },
  299.     { s_achBv,    sizeof(s_achBv)-1,    COrgMod::eSubtype_biovar },
  300.     { s_achF,     sizeof(s_achF)-1,     COrgMod::eSubtype_forma },
  301.     { s_achFo,    sizeof(s_achFo)-1,    COrgMod::eSubtype_forma },
  302.     { s_achGrp,   sizeof(s_achGrp)-1,   COrgMod::eSubtype_group },
  303.     { NULL,       0,                    COrgMod::eSubtype_other }
  304. };
  305. static int
  306. s_NofTokens( const string& s )
  307. {
  308.     int nof = 0;
  309.     char first, last, c;
  310.     int bracket_level, token;
  311.     if( !s.empty() ) {
  312. string::size_type pos = 0;
  313. while( pos < s.size() ) {
  314.     bracket_level= 0;
  315.     token = 0;
  316.     do { // Skip heading white space
  317. first= s[pos++];
  318.     } while( (isspace(first) || iscntrl(first)) &&
  319.      pos < s.size() );
  320.     
  321.     switch( first ) {
  322.     case '"': last= '"'; break;
  323.     case '(': last= ')'; break;
  324.     case '{': last= '}'; break;
  325.     case '[': last= ']'; break;
  326.     default:  last= 0;   break;
  327.     }
  328.     for(; pos < s.size(); ++pos) {
  329. c = s[pos];
  330. if( !isalnum(c) ) {
  331.     if( last == 0 ) {
  332. if( first == c ) {
  333.     ++bracket_level;
  334. }
  335. if( last == c && (!bracket_level--) ) {
  336.     ++pos;
  337.     break;
  338. }
  339.     } else {
  340. if( c == '.' || isspace(c) || iscntrl(c) ) {
  341.     ++pos;
  342.     break;
  343. }
  344.     }
  345. } else {
  346.     token = 1;
  347. }
  348.     }
  349.     nof += token;
  350. }
  351.     }            
  352.     return nof;
  353. }
  354. COrgMod::ESubtype
  355. COrgRefCache::GetSubtypeFromName( string& sName )
  356. {
  357.     static const string s_sSubspCf( "subsp. cf." );
  358.     static const string s_sSubspAff( "subsp. aff." );
  359.     string::size_type pos;
  360.     if( sName.find('.') == string::npos ) {
  361. return COrgMod::eSubtype_other;
  362.     }
  363.     /* ignore subsp. cf. and subsp. aff. */
  364.     if( NStr::FindNoCase( sName, s_sSubspCf ) != string::npos ) {
  365. return COrgMod::eSubtype_other;
  366.     }
  367.     if( NStr::FindNoCase( sName, s_sSubspAff ) != string::npos ) {
  368. return COrgMod::eSubtype_other;
  369.     }
  370.     /* check for subsp */
  371.     SSubtypeAbbr* pSubtypeAbbr = &s_aSubtypes[0];
  372.     while( pSubtypeAbbr->m_eSubtype != COrgMod::eSubtype_other ) {
  373. if( (pos=NStr::FindNoCase( sName,
  374.        string(pSubtypeAbbr->m_pchAbbr,
  375.       pSubtypeAbbr->m_nAbbrLen) )) != NPOS ) {
  376.     sName.erase( pos, pSubtypeAbbr->m_nAbbrLen );
  377.     sName = NStr::TruncateSpaces( sName, NStr::eTrunc_Begin );
  378.     if( pSubtypeAbbr->m_eSubtype == COrgMod::eSubtype_sub_species
  379. && s_NofTokens( sName ) != 1 ) {
  380. break; // Return other
  381.     }
  382.     return pSubtypeAbbr->m_eSubtype;
  383. }
  384. ++pSubtypeAbbr;
  385.     }
  386.     return COrgMod::eSubtype_other;
  387. }
  388. bool
  389. COrgRefCache::BuildOrgModifier( CTaxon1Node* pNode,
  390.                                 COrgName& on,
  391.                                 CTaxon1Node* pParent )
  392. {
  393.     CTaxon1Node* pTmp;
  394.     CRef<COrgMod> pMod( new COrgMod );
  395.     if( !pParent && !pNode->IsRoot() ) {
  396.         pTmp = pNode->GetParent();
  397.         while( !pTmp->IsRoot() ) {
  398.             int prank = pTmp->GetRank();
  399.             if((prank == GetSubspeciesRank()) || 
  400.                (prank == GetSpeciesRank()) ||
  401.                (prank == GetGenusRank())) {
  402.                 pParent = pTmp;
  403.                 break;
  404.             }
  405.             pTmp = pTmp->GetParent();
  406.         }
  407.     }
  408.     string::size_type pos = 0;
  409.     if( pParent ) { // Get rid of parent prefix
  410.         pos = s_AfterPrefix( pNode->GetName(),
  411.                              pParent->GetName() );
  412.     }
  413.     pMod->SetSubname().assign( pNode->GetName(), pos,
  414.                                pNode->GetName().size()-pos );
  415.     pMod->SetSubtype( GetSubtypeFromName( pMod->SetSubname() ) );
  416.     if( pMod->GetSubtype() == COrgMod_Base::eSubtype_sub_species &&
  417. pNode->GetRank() != GetSubspeciesRank() ) {
  418.         pMod->SetSubtype( COrgMod_Base::eSubtype_other );
  419.     }
  420.     if( pMod->GetSubtype() == COrgMod_Base::eSubtype_other ) {
  421. int rank = pNode->GetRank();
  422. if( rank == GetSubspeciesRank() ) {
  423.             if( s_NofTokens( pNode->GetName() ) == 3 ) {
  424. // Assign only "Name1 ssp. Name2" or "Name1 subsp. Name2"  
  425. pMod->SetSubtype( COrgMod_Base::eSubtype_sub_species );
  426.     }
  427. } else if( rank == GetVarietyRank() ) {
  428.     pMod->SetSubtype( COrgMod_Base::eSubtype_variety );
  429. } else if( rank == GetFormaRank() ) {
  430.     pMod->SetSubtype( COrgMod_Base::eSubtype_forma );
  431. } else if( pParent && pParent->GetRank() == GetSubspeciesRank() ) {
  432.     pMod->SetSubtype( COrgMod_Base::eSubtype_strain );
  433. } else { // Do not insert invalid modifier
  434.     return false;
  435. }
  436.     }
  437.     // Store it into list
  438.     on.SetMod().push_back( pMod );
  439.     return true;
  440. }
  441. bool
  442. COrgRefCache::SetBinomialName( CTaxon1Node& node, COrgName& on )
  443. {
  444.     CTaxon1Node* pSpec = ( NULL );
  445.     CTaxon1Node* pSubspec = ( NULL );
  446.     CTaxon1Node* pGenus = ( NULL );
  447.     CTaxon1Node* pSubgen = ( NULL );
  448.     CTaxon1Node* pNode = ( &node );
  449.     string::size_type pos(0);
  450.     do {
  451.         int rank( pNode->GetRank() );
  452.         if( rank == GetSubspeciesRank())
  453.             pSubspec = pNode;
  454.         else if( rank == GetSpeciesRank())
  455.             pSpec = pNode;
  456.         else if( rank == GetSubgenusRank())
  457.             pSubgen = pNode;
  458.         else if(rank == GetGenusRank()) {
  459.             pGenus = pNode;
  460.             break;
  461.         }
  462.         pNode = pNode->GetParent();
  463.     } while( pNode && !pNode->IsRoot() );
  464.     pNode = &node;
  465.     if( !pGenus ) {
  466.         if( !pSubgen )
  467.             return false;
  468.         else
  469.             pGenus = pSubgen;
  470.     }
  471.     CBinomialOrgName& bon = ( on.SetName().SetBinomial() );
  472.     bon.SetGenus( pGenus->GetName() );
  473.     if( pSpec ) { // we have a species in lineage
  474.         bon.SetSpecies().assign( pSpec->GetName(),
  475.                                  pos=s_AfterPrefix( pSpec->GetName(),
  476.                                                     pGenus->GetName() ),
  477.                                  pSpec->GetName().size() - pos );
  478.         if( pSubspec ) { // we also have a subspecies in lineage
  479.             bon.SetSubspecies().assign( pSubspec->GetName(),
  480.                                         pos=s_AfterPrefix(pSubspec->GetName(),
  481.                                                           pSpec->GetName()),
  482.                                         pSubspec->GetName().size() - pos );
  483.         }
  484.         if( pNode != pSpec ) {
  485.             BuildOrgModifier( pNode, on );
  486.         }
  487.         return true;
  488.     }
  489.     // no species in lineage
  490.     if( pSubspec ) { // we have no species but we have subspecies
  491.         bon.SetSubspecies().assign( pSubspec->GetName(),
  492.                                     pos=s_AfterPrefix(pSubspec->GetName(),
  493.                                                       pGenus->GetName()),
  494.                                     pSubspec->GetName().size() - pos );
  495.         BuildOrgModifier( pNode, on,
  496.                           pNode==pSubspec ? pGenus : pSubspec );
  497.         return true;
  498.     }
  499.   
  500.     // we have no species, no subspecies
  501.     // but we are under species level (varietas or forma)
  502.     BuildOrgModifier( pNode, on, pGenus );
  503.     return true;
  504. }
  505. bool
  506. COrgRefCache::SetPartialName( CTaxon1Node& node, COrgName& on )
  507. {
  508.     CTaxElement* pTaxElem = ( new CTaxElement );
  509.     int rank_id= node.GetRank();
  510.     
  511.     CPartialOrgName& pon = ( on.SetName().SetPartial() );
  512.     pon.Set().push_back(CRef<CTaxElement>(pTaxElem));
  513.     if( rank_id == GetFamilyRank()) {
  514.         pTaxElem->SetFixed_level( CTaxElement_Base::eFixed_level_family );
  515.     }
  516.     else if(rank_id == GetOrderRank()) {
  517.         pTaxElem->SetFixed_level( CTaxElement_Base::eFixed_level_order );
  518.     }
  519.     else if(rank_id == GetClassRank()) {
  520.         pTaxElem->SetFixed_level( CTaxElement_Base::eFixed_level_class );
  521.     }
  522.     else {
  523.         pTaxElem->SetFixed_level( CTaxElement_Base::eFixed_level_other );
  524.         pTaxElem->SetLevel( GetRankName( rank_id ) );
  525.     }
  526.     pTaxElem->SetName( node.GetName() );
  527.     return true;
  528. }
  529. bool
  530. COrgRefCache::BuildOrgRef( CTaxon1Node& node, COrg_ref& org, bool& is_species )
  531. {
  532.     // Init ranks here
  533.     if( !InitRanks() || !InitNameClasses() || !InitDivisions() )
  534.         return false;
  535.     CTaxon1_req  req;
  536.     CTaxon1_resp resp;
  537.     req.SetGetorgnames( node.GetTaxId() );
  538.     if( m_host.SendRequest( req, resp ) ) {
  539.         if( resp.IsGetorgnames() ) {
  540.             // Correct response, return object
  541.             list< CRef< CTaxon1_name > >&
  542.                 lLin = ( resp.SetGetorgnames() );
  543.             // Save taxname
  544.             org.SetTaxname().swap( lLin.front()->SetOname() );
  545.             lLin.pop_front();
  546.             list< CRef< CTaxon1_name > >::iterator i;
  547.             // Find preferred common name
  548.             int pref_cls = GetPreferredCommonNameClass();
  549.             for( i = lLin.begin(); i != lLin.end(); ++i ) {
  550.                 if( (*i)->CanGetCde() && (*i)->GetCde() == pref_cls ) {
  551.                     org.SetCommon().swap( (*i)->SetOname() );
  552.                     lLin.erase( i );
  553.                     break;
  554.                 }
  555.             }
  556.             int syn_cls(GetSynonymNameClass());
  557.             int comm_cls(GetCommonNameClass());
  558.             for( i = lLin.begin(); i != lLin.end(); ++i ) {
  559. if( (*i)->CanGetCde() ) {
  560.     int cls = (*i)->GetCde();
  561.     if( cls == syn_cls || cls == comm_cls ) {
  562. org.SetSyn().push_back( (*i)->GetOname() );
  563.     }
  564. }
  565.             }
  566.             // Set taxid as db tag
  567.             org.SetTaxId( node.GetTaxId() );
  568.             COrgName& on = ( org.SetOrgname() );
  569.             short div_id( node.GetDivision() );
  570.             if( GetDivisionCode( div_id ) ) {
  571.                 on.SetDiv( GetDivisionCode( div_id ) );
  572.             }
  573.             on.SetGcode( node.GetGC() );
  574.     if( node.GetMGC() > 0 ) {
  575. on.SetMgcode( node.GetMGC() );
  576.     }
  577.             // Build lineage
  578.             CTaxon1Node* pNode;
  579.             if( !node.IsRoot() ) {
  580.                 pNode = node.GetParent();
  581. on.SetLineage(kEmptyStr);
  582.                 s_BuildLineage( on.SetLineage(), pNode, 0,
  583. GetSpeciesRank() );
  584.                 if( on.GetLineage().empty() ) {
  585.                     on.ResetLineage();
  586. }
  587.             }
  588.             // Set rank
  589.             int rank_id( node.GetRank() );
  590.             is_species = (rank_id >= GetSpeciesRank());
  591.             // correct level by lineage if node has no rank
  592.             if( rank_id < 0 && !node.IsRoot() ) {
  593.                 pNode = node.GetParent();
  594.                 while( !pNode->IsRoot() ) {
  595.                     int rank( pNode->GetRank() );
  596.                     if(rank >= 0) {
  597.                         is_species= (rank >= GetSpeciesRank()-1);
  598.                         break;
  599.                     }
  600.                     pNode = pNode->GetParent();
  601.                 }
  602.             }
  603.             // Create name
  604.             if(is_species) {
  605.                 /* we are on species level or below */
  606.      
  607.                 /* check for viruses */
  608.                 if( div_id == GetVirusesDivision()
  609.                     || div_id == GetPhagesDivision() ) {
  610.                     /* this is a virus */
  611.                     /* virus */
  612.                     if( rank_id == GetSpeciesRank() ) {
  613.                         /* we are on species level */
  614.                         on.SetName().SetVirus( node.GetName() );
  615.                     } else {
  616.                         /* we are below species */
  617.                         /* first try to find species or min rank which
  618.                            below species but above us */
  619.                         pNode = 0;
  620.                         CTaxon1Node* pTmp = ( node.GetParent() );
  621.                         while( pTmp && !pTmp->IsRoot() ) {
  622.                             int rank(pTmp->GetRank());
  623.                             if( rank >= GetSpeciesRank() ) {
  624.                                 pNode = pTmp;
  625.                                 if( rank == GetSpeciesRank() )
  626.                                     break;
  627.                             } else if( rank >= 0 )
  628.                                 break;
  629.                             pTmp = pTmp->GetParent();
  630.                         }
  631.                         if( !pNode ) {// we have species or something above us
  632.                             pNode = &node;
  633.                         }
  634.                         on.SetName().SetVirus( pNode->GetName() );
  635.                         // Add modifier to orgname
  636.                         BuildOrgModifier( &node, on );
  637.                     } // non species rank
  638.                 } else if( !SetBinomialName( node, on ) ) {
  639.                     // name is not binomial: set partial
  640.                     SetPartialName( node, on );
  641.                 }
  642.             } else { // above species
  643.                 SetPartialName( node, on );
  644.             }
  645.     // Add some genbank names as organism modifiers
  646.     if( org.IsSetOrgname() ) { // OrgName is not empty
  647. for( i = lLin.begin(); i != lLin.end(); ++i ) {
  648.     if( (*i)->CanGetCde() ) {
  649. int cde = (*i)->GetCde();
  650. COrgMod::ESubtype stype = (COrgMod::ESubtype)0;
  651. if( cde == GetGBAcronymNameClass() ) {
  652.     stype = COrgMod::eSubtype_gb_acronym;
  653. } else if( cde == GetGBSynonymNameClass() ) {
  654.     stype = COrgMod::eSubtype_gb_synonym;
  655. } else if( cde == GetGBAnamorphNameClass() ) {
  656.     stype = COrgMod::eSubtype_gb_anamorph;
  657. }
  658. if( stype ) {
  659.     CRef<COrgMod> pMod( new COrgMod );
  660.     pMod->SetSubname().swap( (*i)->SetOname() );
  661.     pMod->SetSubtype( stype );
  662.     on.SetMod().push_back( pMod );
  663. }
  664.     }
  665. }
  666.     }
  667.         } else {
  668.             m_host.SetLastError
  669.                 ("Unable to get orgref: Response is not Getorgnames");
  670.             return false;
  671.         }
  672.     } else
  673.         return false;
  674.     return true;
  675. }
  676. bool
  677. COrgRefCache::Insert1( CTaxon1Node& node )
  678. {
  679.     bool is_species( false );
  680.     struct SCacheEntry* pEntry = ( new SCacheEntry );
  681.     pEntry->m_pTax1 = new CTaxon1_data;
  682.     pEntry->m_pTax2 = NULL;
  683.     pEntry->m_pTreeNode = &node;
  684.     COrg_ref& org = ( pEntry->m_pTax1->SetOrg() );
  685.     if( !BuildOrgRef( node, org, is_species ) ) {
  686.         delete pEntry;
  687.         return false;
  688.     }
  689.     // Set division code
  690.     if( GetDivisionCode(node.GetDivision()) ) {
  691.         pEntry->m_pTax1->SetDiv()
  692.             .assign( GetDivisionCode(node.GetDivision()) );
  693.     }
  694.     // Set species level
  695.     pEntry->m_pTax1->SetIs_species_level( is_species );
  696.     // Remove last element from list
  697.     if( m_lCache.size() >= m_nCacheCapacity ) {
  698.         CTaxon1Node* pNode = ( m_lCache.back()->m_pTreeNode );
  699.         pNode->m_cacheEntry = NULL;
  700.         delete m_lCache.back();
  701.         m_lCache.pop_back();
  702.     }
  703.     
  704.     node.m_cacheEntry = pEntry;
  705.     m_lCache.push_front( pEntry );
  706.     return true;
  707. }
  708. bool
  709. COrgRefCache::Insert2( CTaxon1Node& node )
  710. {
  711.     bool is_species( false );
  712.     struct SCacheEntry* pEntry = ( new SCacheEntry );
  713.     pEntry->m_pTax1 = NULL;
  714.     pEntry->m_pTax2 = new CTaxon2_data;
  715.     pEntry->m_pTreeNode = &node;
  716.     pEntry->m_pTax2->SetIs_uncultured( node.IsUncultured() );
  717.     COrg_ref& org = pEntry->m_pTax2->SetOrg();
  718.     if( !BuildOrgRef( node, org, is_species ) ) {
  719.         delete pEntry;
  720.         return false;
  721.     }
  722.     // Set blast names
  723.     CTaxon1Node* pNode = ( &node );
  724.     while( !pNode->IsRoot() ) {
  725.         if( !pNode->GetBlastName().empty() ) {
  726.             pEntry->m_pTax2->SetBlast_name()
  727.                 .push_back( pNode->GetBlastName() );
  728.         }
  729.         pNode = pNode->GetParent();
  730.     }
  731.     // Set species level
  732.     pEntry->m_pTax2->SetIs_species_level( is_species );
  733.     // Remove last element from list
  734.     if( m_lCache.size() >= m_nCacheCapacity ) {
  735.         pNode = m_lCache.back()->m_pTreeNode;
  736.         pNode->m_cacheEntry = NULL;
  737.         delete m_lCache.back();
  738.         m_lCache.pop_back();
  739.     }
  740.     
  741.     node.m_cacheEntry = pEntry;
  742.     m_lCache.push_front( pEntry );
  743.     return true;
  744. }
  745. CTaxon1_data*
  746. COrgRefCache::SCacheEntry::GetData1()
  747. {
  748.     if( ! m_pTax1 ) {
  749.         m_pTax1 = new CTaxon1_data;
  750.         if( m_pTax2->IsSetOrg() ) {
  751.             m_pTax1->SetOrg( m_pTax2->SetOrg() );
  752. }
  753.         if( m_pTax2->GetOrg().GetOrgname().CanGetDiv() ) {
  754.             m_pTax1->SetDiv( m_pTax2->GetOrg().GetOrgname().GetDiv() );
  755.         } else {
  756.             m_pTax1->SetDiv( kEmptyStr );
  757. }
  758.         m_pTax1->SetIs_species_level(m_pTax2->GetIs_species_level());
  759.     }
  760.     return m_pTax1;
  761. }
  762. CTaxon2_data*
  763. COrgRefCache::SCacheEntry::GetData2()
  764. {
  765.     if( ! m_pTax2 ) {
  766.         m_pTax2 = new CTaxon2_data;
  767.         if( m_pTax1->IsSetOrg() ) {
  768.             m_pTax2->SetOrg( m_pTax1->SetOrg() );
  769. }
  770.         CTaxon1Node* pNode = ( m_pTreeNode );
  771.         while( !pNode->IsRoot() ) {
  772.             if( !pNode->GetBlastName().empty() ) {
  773.                 m_pTax2->SetBlast_name().push_back( pNode->GetBlastName() );
  774.             }
  775.             pNode = pNode->GetParent();
  776.         }
  777.         m_pTax2->SetIs_uncultured( m_pTreeNode->IsUncultured() );
  778.         m_pTax2->SetIs_species_level(m_pTax1->GetIs_species_level());
  779.     }
  780.     return m_pTax2;
  781. }
  782. int
  783. COrgRefCache::FindRankByName( const char* pchName ) const
  784. {
  785.     for( TRankMapCI ci = m_rankStorage.begin();
  786.          ci != m_rankStorage.end();
  787.          ++ci )
  788.         if( ci->second.compare( pchName ) == 0 )
  789.             return ci->first;
  790.     return -1000;
  791. }
  792. const char*
  793. COrgRefCache::GetRankName( int rank ) const
  794. {
  795.     TRankMapCI ci( m_rankStorage.find( rank ) );
  796.     if( ci != m_rankStorage.end() ) {
  797.         return ci->second.c_str();
  798.     }
  799.     return NULL;
  800. }
  801. bool
  802. COrgRefCache::InitRanks()
  803. {
  804.     if( m_rankStorage.size() == 0 ) {
  805.         CTaxon1_req  req;
  806.         CTaxon1_resp resp;
  807.         req.SetGetranks();
  808.         if( m_host.SendRequest( req, resp ) ) {
  809.             if( resp.IsGetranks() ) {
  810.                 // Correct response, return object
  811.                 const list< CRef< CTaxon1_info > >&
  812.                     lRanks = ( resp.GetGetranks() );
  813.                 // Fill in storage
  814.                 for( list< CRef< CTaxon1_info > >::const_iterator
  815.                          i = lRanks.begin();
  816.                      i != lRanks.end(); ++i ) {
  817.                     m_rankStorage
  818.                         .insert( TRankMap::value_type((*i)->GetIval1(),
  819.                                                       (*i)->GetSval()) );
  820. }
  821.             } else { // Internal: wrong respond type
  822.                 m_host.SetLastError( "Response type is not Getranks" );
  823.                 return false;
  824.             }
  825.         }
  826.         m_nSuperkingdomRank = FindRankByName( "superkingdom" );
  827.         if( m_nSuperkingdomRank < -10 ) {
  828.             m_host.SetLastError( "Superkingdom rank was not found" );
  829.             return false;
  830.         }
  831.         m_nFamilyRank = FindRankByName( "family" );
  832.         if( m_nFamilyRank < -10 ) {
  833.             m_host.SetLastError( "Family rank was not found" );
  834.             return false;
  835.         }
  836.         m_nOrderRank = FindRankByName( "order" );
  837.         if( m_nOrderRank < -10 ) {
  838.             m_host.SetLastError( "Order rank was not found" );
  839.             return false;
  840.         }
  841.         m_nClassRank = FindRankByName( "class" );
  842.         if( m_nClassRank < -10 ) {
  843.             m_host.SetLastError( "Class rank was not found" );
  844.             return false;
  845.         }
  846.         m_nGenusRank = FindRankByName( "genus" );
  847.         if( m_nGenusRank < -10 ) {
  848.             m_host.SetLastError( "Genus rank was not found" );
  849.             return false;
  850.         }
  851.         m_nSubgenusRank = FindRankByName( "subgenus" );
  852.         if( m_nSubgenusRank < -10 ) {
  853.             m_host.SetLastError( "Subgenus rank was not found" );
  854.             return false;
  855.         }
  856.         m_nSpeciesRank = FindRankByName( "species" );
  857.         if( m_nSpeciesRank < -10 ) {
  858.             m_host.SetLastError( "Species rank was not found" );
  859.             return false;
  860.         }
  861.         m_nSubspeciesRank = FindRankByName( "subspecies" );
  862.         if( m_nSubspeciesRank < -10 ) {
  863.             m_host.SetLastError( "Subspecies rank was not found" );
  864.             return false;
  865.         }
  866.         m_nFormaRank = FindRankByName( "forma" );
  867.         if( m_nFormaRank < -10 ) {
  868.             m_host.SetLastError( "Forma rank was not found" );
  869.             return false;
  870.         }
  871.         m_nVarietyRank = FindRankByName( "varietas" );
  872.         if( m_nVarietyRank < -10 ) {
  873.             m_host.SetLastError( "Variety rank was not found" );
  874.             return false;
  875.         }
  876.     }
  877.     return true;
  878. }
  879. const char*
  880. COrgRefCache::GetNameClassName( short nc ) const
  881. {
  882.     TNameClassMapCI ci( m_ncStorage.find( nc ) );
  883.     if( ci != m_ncStorage.end() ) {
  884.         return ci->second.c_str();
  885.     }
  886.     return NULL;
  887. }
  888. short
  889. COrgRefCache::FindNameClassByName( const char* pchName ) const
  890. {
  891.     for( TNameClassMapCI ci = m_ncStorage.begin();
  892.          ci != m_ncStorage.end();
  893.          ++ci )
  894.         if( ci->second.compare( pchName ) == 0 )
  895.             return ci->first;
  896.     return -1;
  897. }
  898. bool
  899. COrgRefCache::InitNameClasses()
  900. {
  901.     if( m_ncStorage.size() == 0 ) {
  902.         CTaxon1_req  req;
  903.         CTaxon1_resp resp;
  904.         req.SetGetcde();
  905.         if( m_host.SendRequest( req, resp ) ) {
  906.             if( resp.IsGetcde() ) {
  907.                 // Correct response, return object
  908.                 const list< CRef< CTaxon1_info > >&
  909.                     l = ( resp.GetGetcde() );
  910.                 // Fill in storage
  911.                 for( list< CRef< CTaxon1_info > >::const_iterator
  912.                          i = l.begin();
  913.                      i != l.end(); ++i )
  914.                     m_ncStorage
  915.                         .insert( TNameClassMap::value_type((*i)->GetIval1(),
  916.                                                            (*i)->GetSval()) );
  917.             } else { // Internal: wrong respond type
  918.                 m_host.SetLastError( "Response type is not Getcde" );
  919.                 return false;
  920.             }
  921.         }
  922.         m_ncPrefCommon = FindNameClassByName( "genbank common name" );
  923.         if( m_ncPrefCommon < 0 ) {
  924.             m_host.SetLastError( "Genbank common name class was not found" );
  925.             return false;
  926.         }
  927.         m_ncCommon = FindNameClassByName( "common name" );
  928.         if( m_ncCommon < 0 ) {
  929.             m_host.SetLastError( "Common name class was not found" );
  930.             return false;
  931.         }
  932.         m_ncSynonym = FindNameClassByName( "synonym" );
  933.         if( m_ncSynonym < 0 ) {
  934.             m_host.SetLastError( "Synonym name class was not found" );
  935.             return false;
  936.         }
  937. m_ncGBAcronym= FindNameClassByName("genbank acronym");
  938.         if( m_ncGBAcronym < 0 ) {
  939.             m_host.SetLastError( "Genbank acrony name class was not found" );
  940.             return false;
  941.         }
  942. m_ncGBSynonym= FindNameClassByName("genbank synonym");
  943.         if( m_ncGBSynonym < 0 ) {
  944.             m_host.SetLastError( "Genbank synonym name class was not found" );
  945.             return false;
  946.         }
  947. m_ncGBAnamorph= FindNameClassByName("genbank anamorph");
  948.         if( m_ncGBAnamorph < 0 ) {
  949.             m_host.SetLastError( "Genbank anamorph name class was not found" );
  950.             return false;
  951.         }
  952.     }
  953.     return true;
  954. }
  955. short
  956. COrgRefCache::FindDivisionByCode( const char* pchCode ) const
  957. {
  958.     for( TDivisionMapCI ci = m_divStorage.begin();
  959.          ci != m_divStorage.end();
  960.          ++ci ) {
  961.         const char* cp = ( ci->second.m_sCode.c_str() );
  962.         if( strcmp( cp, pchCode ) == 0 )
  963.             return ci->first;
  964.     }
  965.     return -1;
  966. }
  967. const char*
  968. COrgRefCache::GetDivisionCode( short div_id ) const
  969. {
  970.     TDivisionMapCI ci( m_divStorage.find( div_id ) );
  971.     if( ci != m_divStorage.end() ) {
  972.         return ci->second.m_sCode.c_str();
  973.     }
  974.     return NULL;
  975. }
  976. const char*
  977. COrgRefCache::GetDivisionName( short div_id ) const
  978. {
  979.     TDivisionMapCI ci( m_divStorage.find( div_id ) );
  980.     if( ci != m_divStorage.end() ) {
  981.         return ci->second.m_sName.c_str();
  982.     }
  983.     return NULL;
  984. }
  985. bool
  986. COrgRefCache::InitDivisions()
  987. {
  988.     if( m_divStorage.size() == 0 ) {
  989.         CTaxon1_req  req;
  990.         CTaxon1_resp resp;
  991.         req.SetGetdivs();
  992.         if( m_host.SendRequest( req, resp ) ) {
  993.             if( resp.IsGetdivs() ) {
  994.                 // Correct response, return object
  995.                 const list< CRef< CTaxon1_info > >&
  996.                     l = ( resp.GetGetdivs() );
  997.                 // Fill in storage
  998.                 for( list< CRef< CTaxon1_info > >::const_iterator
  999.                          i = l.begin();
  1000.                      i != l.end(); ++i ) {
  1001.                     SDivision& div = ( m_divStorage[(*i)->GetIval1()] );
  1002.                     div.m_sName.assign( (*i)->GetSval() );
  1003.                     int code = (*i)->GetIval2();
  1004.                     for(int k= 0; k < 3; k++) {
  1005.                         div.m_sCode.append( 1U, (code >> (8*(3-k))) & 0xFF );
  1006.                     }
  1007.                     div.m_sCode.append( 1U, code & 0xFF );
  1008.                 }
  1009.             } else { // Internal: wrong response type
  1010.                 m_host.SetLastError( "Response type is not Getdivs" );
  1011.                 return false;
  1012.             }
  1013.         }
  1014.         if( (m_divViruses = FindDivisionByCode( "VRL" )) < 0 ) {
  1015.             m_host.SetLastError( "Viruses division was not found" );
  1016.             return false;
  1017.         }
  1018.         if( (m_divPhages = FindDivisionByCode( "PHG" )) < 0 ) {
  1019.             m_host.SetLastError( "Phages division was not found" );
  1020.             return false;
  1021.         }
  1022.     }
  1023.     return true;
  1024. }
  1025. void
  1026. COrgRefCache::SetIndexEntry( int id, CTaxon1Node* pNode )
  1027. {
  1028.     m_ppEntries[id] = pNode;
  1029. }
  1030. //=======================================================
  1031. //
  1032. //   Iterators implementation
  1033. //
  1034. bool
  1035. CTaxTreeConstIterator::IsLastChild() const
  1036. {
  1037.     const CTreeContNodeBase* pOldNode = m_it->GetNode();
  1038.     bool bResult = true;
  1039.     while( m_it->GoParent() ) {
  1040. if( IsVisible( m_it->GetNode() ) ) {
  1041.     const CTreeContNodeBase* pParent = m_it->GetNode();
  1042.     m_it->GoNode( pOldNode );
  1043.     while( m_it->GetNode() != pParent ) {
  1044. if( m_it->GoSibling() ) {
  1045.     bResult = !NextVisible( pParent );
  1046.     break;
  1047. }
  1048. if( !m_it->GoParent() ) {
  1049.     break;
  1050. }
  1051.     }
  1052.     break;
  1053. }
  1054.     }
  1055.     m_it->GoNode( pOldNode );
  1056.     return bResult;
  1057. }
  1058. bool
  1059. CTaxTreeConstIterator::IsFirstChild() const
  1060. {
  1061.     const CTreeContNodeBase* pOldNode = m_it->GetNode();
  1062.     bool bResult = false;
  1063.     while( m_it->GoParent() ) {
  1064. if( IsVisible( m_it->GetNode() ) ) {
  1065.     const CTreeContNodeBase* pParent = m_it->GetNode();
  1066.     if( m_it->GoChild() ) {
  1067. bResult = NextVisible(pParent) && m_it->GetNode() == pOldNode;
  1068.     }
  1069.     break;
  1070. }
  1071.     }
  1072.     m_it->GoNode( pOldNode );
  1073.     return bResult;
  1074. }
  1075. bool
  1076. CTaxTreeConstIterator::IsTerminal() const
  1077. {
  1078.     const CTreeContNodeBase* pOldNode = m_it->GetNode();
  1079.     if( m_it->GoChild() ) {
  1080. bool bResult = NextVisible( pOldNode );
  1081. m_it->GoNode( pOldNode );
  1082. return !bResult;
  1083.     }
  1084.     return true;
  1085. }
  1086. bool
  1087. CTaxTreeConstIterator::NextVisible( const CTreeContNodeBase* pParent ) const
  1088. {
  1089.     if( m_it->GetNode() == pParent ) {
  1090. return false;
  1091.     }
  1092.  next:
  1093.     if( IsVisible( m_it->GetNode() ) ) {
  1094. return true;
  1095.     }
  1096.     if( m_it->GoChild() ) {
  1097. goto next;
  1098.     } else if( m_it->GoSibling() ) {
  1099. goto next;
  1100.     } else {
  1101. while( m_it->GoParent() && m_it->GetNode() != pParent ) {
  1102.     if( m_it->GoSibling() ) {
  1103. goto next;
  1104.     }
  1105. }
  1106.     }
  1107.     return false;
  1108. }
  1109. bool
  1110. CTaxTreeConstIterator::GoParent()
  1111. {
  1112.     const CTreeContNodeBase* pOldNode = m_it->GetNode();
  1113.     bool bResult = false;
  1114.     while( m_it->GoParent() ) {
  1115. if( IsVisible( m_it->GetNode() ) ) {
  1116.     bResult = true;
  1117.     break;
  1118. }
  1119.     }
  1120.     if( !bResult ) {
  1121. m_it->GoNode( pOldNode );
  1122.     }
  1123.     return bResult;
  1124. }
  1125. bool
  1126. CTaxTreeConstIterator::GoChild()
  1127. {
  1128.     const CTreeContNodeBase* pOldNode = m_it->GetNode();
  1129.     bool bResult = false;
  1130.     
  1131.     if( m_it->GoChild() ) {
  1132. bResult = NextVisible( pOldNode );
  1133.     }
  1134.     if( !bResult ) {
  1135. m_it->GoNode( pOldNode );
  1136.     }
  1137.     return bResult;
  1138. }
  1139. bool
  1140. CTaxTreeConstIterator::GoSibling()
  1141. {
  1142.     const CTreeContNodeBase* pOldNode = m_it->GetNode();
  1143.     bool bResult = false;
  1144.     if( GoParent() ) {
  1145. const CTreeContNodeBase* pParent = m_it->GetNode();
  1146. m_it->GoNode( pOldNode );
  1147. while( m_it->GetNode() != pParent ) {
  1148.     if( m_it->GoSibling() ) {
  1149. bResult = NextVisible( pParent );
  1150. break;
  1151.     }
  1152.     if( !m_it->GoParent() ) {
  1153. break;
  1154.     }
  1155. }
  1156. if( !bResult ) {
  1157.     m_it->GoNode( pOldNode );
  1158. }
  1159.     }
  1160.     return bResult;
  1161. }
  1162. bool
  1163. CTaxTreeConstIterator::GoNode( const ITaxon1Node* pNode )
  1164. {
  1165.     const CTreeContNodeBase* pTaxNode = CastIC( pNode );
  1166.     if( pNode && IsVisible( pTaxNode ) ) {
  1167. return m_it->GoNode( pTaxNode );
  1168.     }
  1169.     return false;
  1170. }
  1171. bool
  1172. CTaxTreeConstIterator::GoAncestor(const ITaxon1Node* pINode)
  1173. {
  1174.     const CTreeContNodeBase* pNode = CastIC( pINode );
  1175.     if( pNode && IsVisible( pNode ) ) {
  1176. const CTreeContNodeBase* pOldNode = m_it->GetNode();
  1177.     
  1178. vector< const CTreeContNodeBase* > v;
  1179. do {
  1180.     v.push_back( m_it->GetNode() );
  1181. } while( GoParent() );
  1182. m_it->GoNode( pNode );
  1183. vector< const CTreeContNodeBase* >::const_iterator vi;
  1184. do {
  1185.     vi = find( v.begin(), v.end(), m_it->GetNode() );
  1186.     if( vi != v.end() ) {
  1187. return true;
  1188.     }
  1189. } while( GoParent() );
  1190. // Restore old position
  1191. m_it->GoNode( pOldNode );
  1192.     }
  1193.     return false;
  1194. }
  1195. bool
  1196. CTaxTreeConstIterator::BelongSubtree(const ITaxon1Node* pIRoot) const
  1197. {
  1198.     const CTreeContNodeBase* pRoot = CastIC( pIRoot );
  1199.     if( pRoot && IsVisible( pRoot ) ) {
  1200. const CTreeContNodeBase* pOldNode = m_it->GetNode();
  1201. do {
  1202.     if( IsVisible( m_it->GetNode() ) ) {
  1203. if( m_it->GetNode() == pRoot ) {
  1204.     m_it->GoNode( pOldNode );
  1205.     return true;
  1206. }
  1207.     }
  1208. } while( m_it->GoParent() );
  1209. m_it->GoNode( pOldNode );
  1210.     }
  1211.     return false;
  1212. }
  1213. // check if given node belongs to subtree pointed by cursor
  1214. bool
  1215. CTaxTreeConstIterator::AboveNode(const ITaxon1Node* pINode) const
  1216. {
  1217.     const CTreeContNodeBase* pNode = CastIC( pINode );
  1218.     if( pNode == m_it->GetNode() ) { // Node is not above itself
  1219. return false;
  1220.     }
  1221.     if( pNode && IsVisible( pNode ) ) {
  1222. const CTreeContNodeBase* pOldNode = m_it->GetNode();
  1223. m_it->GoNode( pNode );
  1224. do {
  1225.     if( IsVisible( m_it->GetNode() ) ) {
  1226. if( m_it->GetNode() == pOldNode ) {
  1227.     m_it->GoNode( pOldNode );
  1228.     return true;
  1229. }
  1230.     }
  1231. } while( m_it->GoParent() );
  1232. m_it->GoNode( pOldNode );
  1233.     }
  1234.     return false;
  1235. }
  1236. bool
  1237. CTreeLeavesBranchesIterator::IsVisible( const CTreeContNodeBase* pNode ) const
  1238. {
  1239.     return pNode &&
  1240. ( pNode->IsRoot() || pNode->IsTerminal() ||
  1241.   !pNode->Child()->IsLastChild() );
  1242. }
  1243. bool
  1244. CTreeBestIterator::IsVisible( const CTreeContNodeBase* pNode ) const
  1245. {
  1246.     return pNode &&
  1247. ( pNode->IsRoot() || pNode->IsTerminal() ||
  1248.   !pNode->Child()->IsLastChild() ||
  1249.   !(pNode->IsLastChild() && pNode->IsFirstChild()) );
  1250. }
  1251. bool
  1252. CTreeBlastIterator::IsVisible( const CTreeContNodeBase* pNode ) const
  1253. {
  1254.     return pNode && ( pNode->IsRoot() ||
  1255.       !CastCI(pNode)->GetBlastName().empty() );
  1256. }
  1257. END_objects_SCOPE
  1258. END_NCBI_SCOPE
  1259. /*
  1260.  * $Log: cache.cpp,v $
  1261.  * Revision 1000.3  2004/06/01 19:35:08  gouriano
  1262.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.21
  1263.  *
  1264.  * Revision 6.21  2004/05/19 17:27:10  gorelenk
  1265.  * Added include of PCH - ncbi_pch.hpp
  1266.  *
  1267.  * Revision 6.20  2004/02/04 16:14:44  domrach
  1268.  * New iterator types (modes of operation) are introduced. They include:
  1269.  * full tree, branches'n'leaves, best, and blast. Position inquiry f-ns
  1270.  * IsTerminal(), IsFirstChild(), and IsLastChild() has been moved from
  1271.  * ITreeNode to ITreeIterator. Node loading f-ns() now return the ITreeNode
  1272.  * for tax id.
  1273.  *
  1274.  * Revision 6.19  2003/11/20 15:42:19  ucko
  1275.  * Update for new (saner) treatment of ASN.1 NULLs.
  1276.  *
  1277.  * Revision 6.18  2003/06/23 20:42:08  domrach
  1278.  * New treatment of subspecies names introduced
  1279.  *
  1280.  * Revision 6.17  2003/06/05 20:44:01  domrach
  1281.  * Adjusted to the new CanGetXxx verification methods
  1282.  *
  1283.  * Revision 6.16  2003/05/06 19:53:53  domrach
  1284.  * New functions and interfaces for traversing the cached partial taxonomy tree introduced. Convenience functions GetDivisionName() and GetRankName() were added
  1285.  *
  1286.  * Revision 6.15  2003/03/06 16:13:14  domrach
  1287.  * Typo fix
  1288.  *
  1289.  * Revision 6.14  2003/03/06 16:11:29  domrach
  1290.  * More static initialization work
  1291.  *
  1292.  * Revision 6.13  2003/03/06 16:01:20  domrach
  1293.  * Static initialization corrected for msvc
  1294.  *
  1295.  * Revision 6.12  2003/03/05 21:33:52  domrach
  1296.  * Enhanced orgref processing. Orgref cache capacity control added.
  1297.  *
  1298.  * Revision 6.11  2003/01/21 19:36:22  domrach
  1299.  * Secondary tax id support added. New copy constructor for partial tree support added.
  1300.  *
  1301.  * Revision 6.10  2002/11/08 14:39:52  domrach
  1302.  * Member function GetSuperkingdom() added
  1303.  *
  1304.  * Revision 6.9  2002/11/04 21:29:18  grichenk
  1305.  * Fixed usage of const CRef<> and CRef<> constructor
  1306.  *
  1307.  * Revision 6.8  2002/08/06 15:09:45  domrach
  1308.  * Introducing new genbank name classes
  1309.  *
  1310.  * Revision 6.7  2002/07/25 15:01:56  grichenk
  1311.  * Replaced non-const GetXXX() with SetXXX()
  1312.  *
  1313.  * Revision 6.6  2002/02/14 22:44:50  vakatov
  1314.  * Use STimeout instead of time_t.
  1315.  * Get rid of warnings and extraneous #include's, shuffled code a little.
  1316.  *
  1317.  * Revision 6.5  2002/01/31 00:31:26  vakatov
  1318.  * Follow the renaming of "CTreeCont.hpp" to "ctreecont.hpp".
  1319.  * Get rid of "std::" which is unnecessary and sometimes un-compilable.
  1320.  * Also done some source identation/beautification.
  1321.  *
  1322.  * Revision 6.4  2002/01/30 16:13:37  domrach
  1323.  * Changes made to pass through MSVC compiler. Some src files renamed
  1324.  *
  1325.  * Revision 6.3  2002/01/29 17:17:45  domrach
  1326.  * Confusion with list/set resolved
  1327.  *
  1328.  * Revision 6.2  2002/01/28 21:37:02  domrach
  1329.  * list changed to multiset in BuildOrgRef()
  1330.  *
  1331.  * Revision 6.1  2002/01/28 19:56:10  domrach
  1332.  * Initial checkin of the library implementation files
  1333.  *
  1334.  * ===========================================================================
  1335.  */