src/objects/taxon1/cache.cpp

Go to the documentation of this file.
00001 /* $Id: cache.cpp 103491 2007-05-04 17:18:18Z kazimird $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Author:  Vladimir Soussov, Michael Domrachev
00027  *
00028  * File Description:
00029  *     NCBI Taxonomy information retreival library caching implementation
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             // Correct response, return object
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 { // Internal: wrong respond type
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 ); // Gene bank hidden
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 { // Add the entry from server
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                     // Correct response, return object
00127                     list< CRef<CTaxon1_name> >& lLin = resp.SetTaxalineage();
00128                     CTaxon1Node* pParent = 0;
00129                     pNode   = 0;
00130                     // Check if this is a secondary node
00131                     if( lLin.front()->GetTaxid() != tax_id ) {
00132                         // Secondary node, try to get primary from index
00133                         pNode = m_ppEntries[ lLin.front()->GetTaxid() ];
00134                     }
00135                     if( !pNode ) {
00136                         list< CRef< CTaxon1_name > >::reverse_iterator i;
00137                         // Fill in storage
00138                         for( i = lLin.rbegin(); i != lLin.rend(); ++i ) {
00139                             if( !m_ppEntries[ (*i)->GetTaxid() ] ) {
00140                                 // Create node
00141                                 break;
00142                             } else {
00143                                 pParent = m_ppEntries[ (*i)->GetTaxid() ];
00144                             }
00145                         }
00146                         // Create tree iterator
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 { // Store secondary in index
00159                         m_ppEntries[ tax_id ] = pNode;
00160                     }
00161                     _ASSERT( pNode );
00162                     *ppData = pNode;
00163                     return true;
00164                 } else { // Internal: wrong respond type
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             // Move in the list
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             // Move in the list
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 //         if( pNode->GetRank() > sp_rank-1 ) {
00260 //             s_BuildLineage( str, pNode->GetParent(), 0, sp_rank );
00261 //             return false;
00262 //         } else {
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 { // Skip heading white space
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     /* ignore subsp. cf. and subsp. aff. */
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     /* ignore cf. and aff. */
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     /* check for subsp */
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; // Return other
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 ) { // Get rid of parent prefix
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 { // Do not insert invalid modifier
00492         return false;
00493     }
00494     }
00495     // Store it into list
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 ) { // we have a species in lineage
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 ) { // we also have a subspecies in lineage
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     // no species in lineage
00560     if( pSubspec ) { // we have no species but we have subspecies
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     // we have no species, no subspecies
00575     // but we are under species level (varietas or forma)
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     // Init ranks here
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             // Correct response, return object
00621             list< CRef< CTaxon1_name > >&
00622                 lLin = ( resp.SetGetorgnames() );
00623             // Save taxname
00624             org.SetTaxname().swap( lLin.front()->SetOname() );
00625             lLin.pop_front();
00626 
00627             list< CRef< CTaxon1_name > >::iterator i;
00628             // Find preferred common name
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             // Set taxid as db tag
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             // Build lineage
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             // Set rank
00672             int rank_id( node.GetRank() );
00673 
00674             is_species = (rank_id >= GetSpeciesRank());
00675             // correct level by lineage if node has no rank
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             // Create name
00688             if(is_species) {
00689                 /* we are on species level or below */
00690          
00691                 /* check for viruses */
00692                 if( div_id == GetVirusesDivision()
00693                     || div_id == GetPhagesDivision() ) {
00694                     /* this is a virus */
00695                     /* virus */
00696                     if( rank_id == GetSpeciesRank() ) {
00697                         /* we are on species level */
00698                         on.SetName().SetVirus( node.GetName() );
00699                     } else {
00700                         /* we are below species */
00701                         /* first try to find species or min rank which
00702                            below species but above us */
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 ) {// we have species or something above us
00717                             pNode = &node;
00718                         }
00719                         on.SetName().SetVirus( pNode->GetName() );
00720                         // Add modifier to orgname
00721                         BuildOrgModifier( &node, on );
00722                     } // non species rank
00723                 } else if( !SetBinomialName( node, on ) ) {
00724                     // name is not binomial: set partial
00725                     SetPartialName( node, on );
00726                 }
00727             } else { // above species
00728                 SetPartialName( node, on );
00729             }
00730             // Add some genbank names as organism modifiers
00731             if( org.IsSetOrgname() ) { // OrgName is not empty
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     // Set division code
00779     if( GetDivisionCode(node.GetDivision()) ) {
00780         pEntry->m_pTax1->SetDiv()
00781             .assign( GetDivisionCode(node.GetDivision()) );
00782     }
00783     // Set species level
00784     pEntry->m_pTax1->SetIs_species_level( is_species );
00785     // Remove last element from list
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     // Set blast names
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     // Set species level
00826     pEntry->m_pTax2->SetIs_species_level( is_species );
00827     // Remove last element from list
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                 // Correct response, return object
00915                 const list< CRef< CTaxon1_info > >&
00916                     lRanks = ( resp.GetGetranks() );
00917                 // Fill in storage
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 { // Internal: wrong respond type
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                 // Correct response, return object
01019                 const list< CRef< CTaxon1_info > >&
01020                     l = ( resp.GetGetcde() );
01021                 // Fill in storage
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 { // Internal: wrong respond type
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                 // Correct response, return object
01117                 const list< CRef< CTaxon1_info > >&
01118                     l = ( resp.GetGetdivs() );
01119                 // Fill in storage
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 { // Internal: wrong response type
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 //   Iterators implementation
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         // Restore old position
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 // check if given node belongs to subtree pointed by cursor
01355 bool
01356 CTaxTreeConstIterator::AboveNode(const ITaxon1Node* pINode) const
01357 {
01358     const CTreeContNodeBase* pNode = CastIC( pINode );
01359     if( pNode == m_it->GetNode() ) { // Node is not above itself
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 

Generated on Sun Dec 6 22:39:24 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Dec 07 16:21:09 2009 by modify_doxy.py rev. 173732