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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: seq_id_tree.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 19:24:07  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: seq_id_tree.cpp,v 1000.4 2004/06/01 19:24:07 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: Aleksey Grichenko, Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   Seq-id mapper for Object Manager
  38. *
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include <objmgr/impl/seq_id_tree.hpp>
  42. #include <objmgr/objmgr_exception.hpp>
  43. BEGIN_NCBI_SCOPE
  44. BEGIN_SCOPE(objects)
  45. /////////////////////////////////////////////////////////////////////////////
  46. // to make map<string, something> case-insensitive
  47. struct seqid_string_less
  48. {
  49.     bool operator()(const string& s1, const string& s2) const
  50.     {
  51.         return (NStr::CompareNocase(s1, s2) < 0);
  52.     }
  53. };
  54. ////////////////////////////////////////////////////////////////////
  55. //
  56. //  CSeq_id_***_Tree::
  57. //
  58. //    Seq-id sub-type specific trees
  59. //
  60. CSeq_id_Which_Tree::CSeq_id_Which_Tree(void)
  61. {
  62. }
  63. CSeq_id_Which_Tree::~CSeq_id_Which_Tree(void)
  64. {
  65. }
  66. bool CSeq_id_Which_Tree::HaveMatch(const CSeq_id_Handle& ) const
  67. {
  68.     return true; // Assume have matches by default
  69. }
  70. bool CSeq_id_Which_Tree::IsBetterVersion(const CSeq_id_Handle& /*h1*/,
  71.                                          const CSeq_id_Handle& /*h2*/) const
  72. {
  73.     return false; // No id version by default
  74. }
  75. inline
  76. CSeq_id_Info* CSeq_id_Which_Tree::CreateInfo(void)
  77. {
  78.     return new CSeq_id_Info(this);
  79. }
  80. bool CSeq_id_Which_Tree::HaveReverseMatch(const CSeq_id_Handle& ) const
  81. {
  82.     return false; // Assume no reverse matches by default
  83. }
  84. void CSeq_id_Which_Tree::FindReverseMatch(const CSeq_id_Handle& id,
  85.                                           TSeq_id_MatchList& id_list)
  86. {
  87.     id_list.insert(id);
  88.     return;
  89. }
  90. CSeq_id_Info* CSeq_id_Which_Tree::CreateInfo(const CSeq_id& id)
  91. {
  92.     CRef<CSeq_id> id_ref(new CSeq_id);
  93.     id_ref->Assign(id);
  94.     return new CSeq_id_Info(this, id_ref);
  95. }
  96. void CSeq_id_Which_Tree::DropInfo(const CSeq_id_Info* info)
  97. {
  98.     if ( info->GetCounter() > 0 ) {
  99.         return;
  100.     }
  101.     {{
  102.         TWriteLockGuard guard(m_TreeLock);
  103.         if ( info->GetCounter() > 0 ) {
  104.             return;
  105.         }
  106.         x_Unindex(info);
  107.     }}
  108.     delete info;
  109. }
  110. CSeq_id_Handle CSeq_id_Which_Tree::GetGiHandle(int /*gi*/)
  111. {
  112.     NCBI_THROW(CObjMgrException, eIdMapperError, "Invalid seq-id type");
  113. }
  114. void CSeq_id_Which_Tree::Initialize(vector<CRef<CSeq_id_Which_Tree> >& v)
  115. {
  116.     v.resize(CSeq_id::e_Tpd+1);
  117.     v[CSeq_id::e_not_set].Reset(new CSeq_id_not_set_Tree);
  118.     v[CSeq_id::e_Local].Reset(new CSeq_id_Local_Tree);
  119.     v[CSeq_id::e_Gibbsq].Reset(new CSeq_id_Gibbsq_Tree);
  120.     v[CSeq_id::e_Gibbmt].Reset(new CSeq_id_Gibbmt_Tree);
  121.     v[CSeq_id::e_Giim].Reset(new CSeq_id_Giim_Tree);
  122.     // These three types share the same accessions space
  123.     CRef<CSeq_id_Which_Tree> gb(new CSeq_id_GB_Tree);
  124.     v[CSeq_id::e_Genbank] = gb;
  125.     v[CSeq_id::e_Embl] = gb;
  126.     v[CSeq_id::e_Ddbj] = gb;
  127.     v[CSeq_id::e_Pir].Reset(new CSeq_id_Pir_Tree);
  128.     v[CSeq_id::e_Swissprot].Reset(new CSeq_id_Swissprot_Tree);
  129.     v[CSeq_id::e_Patent].Reset(new CSeq_id_Patent_Tree);
  130.     v[CSeq_id::e_Other].Reset(new CSeq_id_Other_Tree);
  131.     v[CSeq_id::e_General].Reset(new CSeq_id_General_Tree);
  132.     v[CSeq_id::e_Gi].Reset(new CSeq_id_Gi_Tree);
  133.     // see above    v[CSeq_id::e_Ddbj] = gb;
  134.     v[CSeq_id::e_Prf].Reset(new CSeq_id_Prf_Tree);
  135.     v[CSeq_id::e_Pdb].Reset(new CSeq_id_PDB_Tree);
  136.     v[CSeq_id::e_Tpg].Reset(new CSeq_id_Tpg_Tree);
  137.     v[CSeq_id::e_Tpe].Reset(new CSeq_id_Tpe_Tree);
  138.     v[CSeq_id::e_Tpd].Reset(new CSeq_id_Tpd_Tree);
  139. }
  140. /////////////////////////////////////////////////////////////////////////////
  141. // CSeq_id_not_set_Tree
  142. /////////////////////////////////////////////////////////////////////////////
  143. CSeq_id_not_set_Tree::CSeq_id_not_set_Tree(void)
  144. {
  145. }
  146. CSeq_id_not_set_Tree::~CSeq_id_not_set_Tree(void)
  147. {
  148. }
  149. bool CSeq_id_not_set_Tree::Empty(void) const
  150. {
  151.     return true;
  152. }
  153. inline
  154. bool CSeq_id_not_set_Tree::x_Check(const CSeq_id& id) const
  155. {
  156.     return id.Which() == CSeq_id::e_not_set;
  157. }
  158. void CSeq_id_not_set_Tree::DropInfo(const CSeq_id_Info* /*info*/)
  159. {
  160. }
  161. void CSeq_id_not_set_Tree::x_Unindex(const CSeq_id_Info* /*info*/)
  162. {
  163. }
  164. CSeq_id_Handle CSeq_id_not_set_Tree::FindInfo(const CSeq_id& /*id*/) const
  165. {
  166.     LOG_POST(Warning << "CSeq_id_Mapper::GetHandle() -- uninitialized seq-id");
  167.     return CSeq_id_Handle();
  168. }
  169. CSeq_id_Handle CSeq_id_not_set_Tree::FindOrCreate(const CSeq_id& /*id*/)
  170. {
  171.     LOG_POST(Warning << "CSeq_id_Mapper::GetHandle() -- uninitialized seq-id");
  172.     return CSeq_id_Handle();
  173. }
  174. bool CSeq_id_not_set_Tree::HaveMatch(const CSeq_id_Handle& ) const
  175. {
  176.     return false;
  177. }
  178. void CSeq_id_not_set_Tree::FindMatch(const CSeq_id_Handle& /*id*/,
  179.                                      TSeq_id_MatchList& /*id_list*/) const
  180. {
  181.     LOG_POST(Warning << "CSeq_id_Mapper::GetMatchingHandles() -- "
  182.              "uninitialized seq-id");
  183. }
  184. void CSeq_id_not_set_Tree::FindMatchStr(string /*sid*/,
  185.                                         TSeq_id_MatchList& /*id_list*/) const
  186. {
  187. }
  188. bool CSeq_id_not_set_Tree::HaveReverseMatch(const CSeq_id_Handle& /*id*/) const
  189. {
  190.     return false;
  191. }
  192. void CSeq_id_not_set_Tree::FindReverseMatch(const CSeq_id_Handle& /*id*/,
  193.                                             TSeq_id_MatchList& /*id_list*/)
  194. {
  195.     LOG_POST(Warning << "CSeq_id_Mapper::GetReverseMatchingHandles() -- "
  196.              "uninitialized seq-id");
  197. }
  198. /////////////////////////////////////////////////////////////////////////////
  199. // CSeq_id_int_Tree
  200. /////////////////////////////////////////////////////////////////////////////
  201. CSeq_id_int_Tree::CSeq_id_int_Tree(void)
  202. {
  203. }
  204. CSeq_id_int_Tree::~CSeq_id_int_Tree(void)
  205. {
  206. }
  207. bool CSeq_id_int_Tree::Empty(void) const
  208. {
  209.     return m_IntMap.empty();
  210. }
  211. CSeq_id_Handle CSeq_id_int_Tree::FindInfo(const CSeq_id& id) const
  212. {
  213.     _ASSERT(x_Check(id));
  214.     int value = x_Get(id);
  215.     TReadLockGuard guard(m_TreeLock);
  216.     TIntMap::const_iterator it = m_IntMap.find(value);
  217.     if (it != m_IntMap.end()) {
  218.         return CSeq_id_Handle(it->second);
  219.     }
  220.     return CSeq_id_Handle();
  221. }
  222. CSeq_id_Handle CSeq_id_int_Tree::FindOrCreate(const CSeq_id& id)
  223. {
  224.     _ASSERT(x_Check(id));
  225.     int value = x_Get(id);
  226.     TWriteLockGuard guard(m_TreeLock);
  227.     pair<TIntMap::iterator, bool> ins =
  228.         m_IntMap.insert(TIntMap::value_type(value, 0));
  229.     if ( ins.second ) {
  230.         ins.first->second = CreateInfo(id);
  231.     }
  232.     return CSeq_id_Handle(ins.first->second);
  233. }
  234. void CSeq_id_int_Tree::x_Unindex(const CSeq_id_Info* info)
  235. {
  236.     _ASSERT(x_Check(*info->GetSeqId()));
  237.     int value = x_Get(*info->GetSeqId());
  238.     _VERIFY(m_IntMap.erase(value));
  239. }
  240. bool CSeq_id_int_Tree::HaveMatch(const CSeq_id_Handle& ) const
  241. {
  242.     // Only one instance of each int id
  243.     return false;
  244. }
  245. void CSeq_id_int_Tree::FindMatch(const CSeq_id_Handle& id,
  246.                                  TSeq_id_MatchList& id_list) const
  247. {
  248.     // Only one instance of each int id
  249.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  250.     id_list.insert(id);
  251. }
  252. void CSeq_id_int_Tree::FindMatchStr(string sid,
  253.                                     TSeq_id_MatchList& id_list) const
  254. {
  255.     int value;
  256.     try {
  257.         value = NStr::StringToInt(sid);
  258.     }
  259.     catch (const CStringException& /*ignored*/) {
  260.         // Not an integer value
  261.         return;
  262.     }
  263.     TReadLockGuard guard(m_TreeLock);
  264.     TIntMap::const_iterator it = m_IntMap.find(value);
  265.     if (it != m_IntMap.end()) {
  266.         id_list.insert(CSeq_id_Handle(it->second));
  267.     }
  268. }
  269. /////////////////////////////////////////////////////////////////////////////
  270. // CSeq_id_Gibbsq_Tree
  271. /////////////////////////////////////////////////////////////////////////////
  272. bool CSeq_id_Gibbsq_Tree::x_Check(const CSeq_id& id) const
  273. {
  274.     return id.IsGibbsq();
  275. }
  276. int CSeq_id_Gibbsq_Tree::x_Get(const CSeq_id& id) const
  277. {
  278.     return id.GetGibbsq();
  279. }
  280. /////////////////////////////////////////////////////////////////////////////
  281. // CSeq_id_Gibbmt_Tree
  282. /////////////////////////////////////////////////////////////////////////////
  283. bool CSeq_id_Gibbmt_Tree::x_Check(const CSeq_id& id) const
  284. {
  285.     return id.IsGibbmt();
  286. }
  287. int CSeq_id_Gibbmt_Tree::x_Get(const CSeq_id& id) const
  288. {
  289.     return id.GetGibbmt();
  290. }
  291. /////////////////////////////////////////////////////////////////////////////
  292. // CSeq_id_Gi_Tree
  293. /////////////////////////////////////////////////////////////////////////////
  294. CSeq_id_Gi_Tree::CSeq_id_Gi_Tree(void)
  295.     : m_Info(CreateInfo())
  296. {
  297. }
  298. CSeq_id_Gi_Tree::~CSeq_id_Gi_Tree(void)
  299. {
  300.     _ASSERT(m_Info);
  301.     m_Info.Reset();
  302. }
  303. bool CSeq_id_Gi_Tree::Empty(void) const
  304. {
  305.     return true;
  306. }
  307. inline
  308. bool CSeq_id_Gi_Tree::x_Check(const CSeq_id& id) const
  309. {
  310.     return id.IsGi();
  311. }
  312. inline
  313. int CSeq_id_Gi_Tree::x_Get(const CSeq_id& id) const
  314. {
  315.     return id.GetGi();
  316. }
  317. void CSeq_id_Gi_Tree::DropInfo(const CSeq_id_Info* info)
  318. {
  319.     _ASSERT(!m_Info);
  320.     delete info;
  321. }
  322. void CSeq_id_Gi_Tree::x_Unindex(const CSeq_id_Info* /*info*/)
  323. {
  324. }
  325. CSeq_id_Handle CSeq_id_Gi_Tree::GetGiHandle(int gi)
  326. {
  327.     return CSeq_id_Handle(m_Info, gi);
  328. }
  329. CSeq_id_Handle CSeq_id_Gi_Tree::FindInfo(const CSeq_id& id) const
  330. {
  331.     _ASSERT(x_Check(id));
  332.     return CSeq_id_Handle(m_Info, x_Get(id));
  333. }
  334. CSeq_id_Handle CSeq_id_Gi_Tree::FindOrCreate(const CSeq_id& id)
  335. {
  336.     _ASSERT(x_Check(id));
  337.     return CSeq_id_Handle(m_Info, x_Get(id));
  338. }
  339. bool CSeq_id_Gi_Tree::HaveMatch(const CSeq_id_Handle& ) const
  340. {
  341.     // Only one instance of each int id
  342.     return false;
  343. }
  344. void CSeq_id_Gi_Tree::FindMatch(const CSeq_id_Handle& id, TSeq_id_MatchList& id_list) const
  345. {
  346.     // Only one instance of each int id
  347.     id_list.insert(id);
  348. }
  349. void CSeq_id_Gi_Tree::FindMatchStr(string sid,
  350.                                     TSeq_id_MatchList& id_list) const
  351. {
  352.     int value;
  353.     try {
  354.         value = NStr::StringToInt(sid);
  355.     }
  356.     catch (const CStringException& /*ignored*/) {
  357.         // Not an integer value
  358.         return;
  359.     }
  360.     id_list.insert(CSeq_id_Handle(m_Info, value));
  361. }
  362. /////////////////////////////////////////////////////////////////////////////
  363. // CSeq_id_Textseq_Tree
  364. /////////////////////////////////////////////////////////////////////////////
  365. CSeq_id_Textseq_Tree::CSeq_id_Textseq_Tree(void)
  366. {
  367. }
  368. CSeq_id_Textseq_Tree::~CSeq_id_Textseq_Tree(void)
  369. {
  370. }
  371. bool CSeq_id_Textseq_Tree::Empty(void) const
  372. {
  373.     return m_ByName.empty() && m_ByAccession.empty();
  374. }
  375. CSeq_id_Info*
  376. CSeq_id_Textseq_Tree::x_FindVersionEqual(const TVersions& ver_list,
  377.                                          const CTextseq_id& tid) const
  378. {
  379.     ITERATE(TVersions, vit, ver_list) {
  380.         if (x_Get(*(*vit)->GetSeqId()).Equals(tid)) {
  381.             return *vit;
  382.         }
  383.     }
  384.     return 0;
  385. }
  386. CSeq_id_Info* CSeq_id_Textseq_Tree::x_FindInfo(const CTextseq_id& tid) const
  387. {
  388.     TStringMap::const_iterator it;
  389.     if ( tid.IsSetAccession() ) {
  390.         it = m_ByAccession.find(tid.GetAccession());
  391.         if (it == m_ByAccession.end()) {
  392.             return 0;
  393.         }
  394.     }
  395.     else if ( tid.IsSetName() ) {
  396.         it = m_ByName.find(tid.GetName());
  397.         if (it == m_ByName.end()) {
  398.             return 0;
  399.         }
  400.     }
  401.     else {
  402.         return 0;
  403.     }
  404.     return x_FindVersionEqual(it->second, tid);
  405. }
  406. CSeq_id_Handle CSeq_id_Textseq_Tree::FindInfo(const CSeq_id& id) const
  407. {
  408.     // Note: if a record is found by accession, no name is checked
  409.     // even if it is also set.
  410.     _ASSERT(x_Check(id));
  411.     const CTextseq_id& tid = x_Get(id);
  412.     // Can not compare if no accession given
  413.     TReadLockGuard guard(m_TreeLock);
  414.     return CSeq_id_Handle(x_FindInfo(tid));
  415. }
  416. CSeq_id_Handle CSeq_id_Textseq_Tree::FindOrCreate(const CSeq_id& id)
  417. {
  418.     _ASSERT(x_Check(id));
  419.     const CTextseq_id& tid = x_Get(id);
  420.     TWriteLockGuard guard(m_TreeLock);
  421.     CSeq_id_Info* info = x_FindInfo(tid);
  422.     if ( !info ) {
  423.         info = CreateInfo(id);
  424.         if ( tid.IsSetAccession() ) {
  425.             TVersions& ver = m_ByAccession[tid.GetAccession()];
  426.             ITERATE(TVersions, vit, ver) {
  427.                 _ASSERT(!x_Get(*(*vit)->GetSeqId()).Equals(tid));
  428.             }
  429.             ver.push_back(info);
  430.         }
  431.         if ( tid.IsSetName() ) {
  432.             TVersions& ver = m_ByName[tid.GetName()];
  433.             ITERATE(TVersions, vit, ver) {
  434.                 _ASSERT(!x_Get(*(*vit)->GetSeqId()).Equals(tid));
  435.             }
  436.             ver.push_back(info);
  437.         }
  438.     }
  439.     return CSeq_id_Handle(info);
  440. }
  441. void CSeq_id_Textseq_Tree::x_Unindex(const CSeq_id_Info* info)
  442. {
  443.     _ASSERT(x_Check(*info->GetSeqId()));
  444.     const CTextseq_id& tid = x_Get(*info->GetSeqId());
  445.     if ( tid.IsSetAccession() ) {
  446.         TStringMap::iterator it =
  447.             m_ByAccession.find(tid.GetAccession());
  448.         if (it != m_ByAccession.end()) {
  449.             NON_CONST_ITERATE(TVersions, vit, it->second) {
  450.                 if (*vit == info) {
  451.                     it->second.erase(vit);
  452.                     break;
  453.                 }
  454.             }
  455.             if (it->second.empty())
  456.                 m_ByAccession.erase(it);
  457.         }
  458.     }
  459.     if ( tid.IsSetName() ) {
  460.         TStringMap::iterator it = m_ByName.find(tid.GetName());
  461.         if (it != m_ByName.end()) {
  462.             NON_CONST_ITERATE(TVersions, vit, it->second) {
  463.                 if (*vit == info) {
  464.                     it->second.erase(vit);
  465.                     break;
  466.                 }
  467.             }
  468.             if (it->second.empty())
  469.                 m_ByName.erase(it);
  470.         }
  471.     }
  472. }
  473. void CSeq_id_Textseq_Tree::x_FindVersionMatch(const TVersions& ver_list,
  474.                                               const CTextseq_id& tid,
  475.                                               TSeq_id_MatchList& id_list) const
  476. {
  477.     int ver = 0;
  478.     string rel;
  479.     if ( tid.IsSetVersion() )
  480.         ver = tid.GetVersion();
  481.     if ( tid.IsSetRelease() )
  482.         rel = tid.GetRelease();
  483.     ITERATE(TVersions, vit, ver_list) {
  484.         int ver_it = 0;
  485.         string rel_it;
  486.         const CTextseq_id& vit_ref = x_Get(*(*vit)->GetSeqId());
  487.         if ( vit_ref.IsSetVersion() )
  488.             ver_it = vit_ref.GetVersion();
  489.         if ( vit_ref.IsSetRelease() )
  490.             rel_it = vit_ref.GetRelease();
  491.         if (ver != 0 && ver != ver_it) {
  492.             continue;
  493.         }
  494.         if (!rel.empty() && rel != rel_it) {
  495.             continue;
  496.         }
  497.         id_list.insert(CSeq_id_Handle(*vit));
  498.     }
  499. }
  500. void CSeq_id_Textseq_Tree::FindMatch(const CSeq_id_Handle& id,
  501.                                      TSeq_id_MatchList& id_list) const
  502. {
  503.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  504.     const CTextseq_id& tid = x_Get(*id.GetSeqId());
  505.     if ( tid.IsSetAccession() ) {
  506.         TReadLockGuard guard(m_TreeLock);
  507.         TStringMap::const_iterator it = m_ByAccession.find(tid.GetAccession());
  508.         if (it != m_ByAccession.end()) {
  509.             x_FindVersionMatch(it->second, tid, id_list);
  510.         }
  511.     }
  512.     else if ( tid.IsSetName() ) {
  513.         TReadLockGuard guard(m_TreeLock);
  514.         TStringMap::const_iterator it = m_ByName.find(tid.GetName());
  515.         if (it != m_ByName.end()) {
  516.             x_FindVersionMatch(it->second, tid, id_list);
  517.         }
  518.     }
  519. }
  520. void CSeq_id_Textseq_Tree::FindMatchStr(string sid,
  521.                                         TSeq_id_MatchList& id_list) const
  522. {
  523.     TReadLockGuard guard(m_TreeLock);
  524.     // ignore '.' in the search string - cut it out
  525.     sid = sid.substr(0, sid.find('.'));
  526.     // Find by accession
  527.     TStringMap::const_iterator it = m_ByAccession.find(sid);
  528.     if (it == m_ByAccession.end()) {
  529.         it = m_ByName.find(sid);
  530.         if (it == m_ByName.end())
  531.             return;
  532.     }
  533.     ITERATE(TVersions, vit, it->second) {
  534.         id_list.insert(CSeq_id_Handle(*vit));
  535.     }
  536. }
  537. bool CSeq_id_Textseq_Tree::IsBetterVersion(const CSeq_id_Handle& h1,
  538.                                            const CSeq_id_Handle& h2) const
  539. {
  540.     CConstRef<CSeq_id> id1 = h1.GetSeqId();
  541.     _ASSERT(x_Check(*id1));
  542.     CConstRef<CSeq_id> id2 = h2.GetSeqId();
  543.     _ASSERT(x_Check(*id2));
  544.     const CTextseq_id& tid1 = x_Get(*id1);
  545.     const CTextseq_id& tid2 = x_Get(*id2);
  546.     // Compare versions. If only one of the two ids has version,
  547.     // consider it is better.
  548.     if ( tid1.IsSetVersion() ) {
  549.         if ( tid2.IsSetVersion() )
  550.             return tid1.GetVersion() > tid2.GetVersion();
  551.         else
  552.             return true; // Only h1 has version
  553.     }
  554.     return false; // h1 has no version, so it can not be better than h2
  555. }
  556. bool CSeq_id_Textseq_Tree::HaveReverseMatch(const CSeq_id_Handle&) const
  557. {
  558.     return true;
  559. }
  560. void CSeq_id_Textseq_Tree::FindReverseMatch(const CSeq_id_Handle& id,
  561.                                             TSeq_id_MatchList& id_list)
  562. {
  563.     id_list.insert(id);
  564.     CConstRef<CSeq_id> orig_id = id.GetSeqId();
  565.     const CTextseq_id& orig_tid = x_Get(*orig_id);
  566.     CRef<CSeq_id> tmp(new CSeq_id);
  567.     tmp->Assign(*orig_id);
  568.     CTextseq_id& tid = const_cast<CTextseq_id&>(x_Get(*tmp));
  569.     bool A = orig_tid.IsSetAccession();
  570.     bool N = orig_tid.IsSetName();
  571.     bool v = orig_tid.IsSetVersion();
  572.     bool r = orig_tid.IsSetRelease();
  573.     if ( A  &&  (N  ||  v  ||  r) ) {
  574.         // A only
  575.         tid.Reset();
  576.         tid.SetAccession(orig_tid.GetAccession());
  577.         id_list.insert(FindOrCreate(*tmp));
  578.         if ( v  &&  (N  ||  r) ) {
  579.             // A.v
  580.             tid.SetVersion(orig_tid.GetVersion());
  581.             id_list.insert(FindOrCreate(*tmp));
  582.         }
  583.         if ( N ) {
  584.             // N only
  585.             tid.Reset();
  586.             tid.SetName(orig_tid.GetName());
  587.             id_list.insert(FindOrCreate(*tmp));
  588.             if ( v  ||  r ) {
  589.                 if ( r ) {
  590.                     // N.r
  591.                     tid.SetRelease(orig_tid.GetRelease());
  592.                     id_list.insert(FindOrCreate(*tmp));
  593.                     tid.ResetRelease();
  594.                 }
  595.                 // A + N
  596.                 tid.SetAccession(orig_tid.GetAccession());
  597.                 id_list.insert(FindOrCreate(*tmp));
  598.                 if ( v  &&  r ) {
  599.                     // A.v + N
  600.                     tid.SetVersion(orig_tid.GetVersion());
  601.                     id_list.insert(FindOrCreate(*tmp));
  602.                     // A + N.r
  603.                     tid.ResetVersion();
  604.                     tid.SetRelease(orig_tid.GetRelease());
  605.                     id_list.insert(FindOrCreate(*tmp));
  606.                 }
  607.             }
  608.         }
  609.     }
  610.     else if ( N  &&  (v  ||  r) ) {
  611.         // N only
  612.         tid.Reset();
  613.         tid.SetName(orig_tid.GetName());
  614.         id_list.insert(FindOrCreate(*tmp));
  615.         if ( v  &&  r ) {
  616.             tid.SetRelease(orig_tid.GetRelease());
  617.             id_list.insert(FindOrCreate(*tmp));
  618.         }
  619.     }
  620. }
  621. /////////////////////////////////////////////////////////////////////////////
  622. // CSeq_id_GB_Tree
  623. /////////////////////////////////////////////////////////////////////////////
  624. bool CSeq_id_GB_Tree::x_Check(const CSeq_id& id) const
  625. {
  626.     return id.IsGenbank()  ||  id.IsEmbl()  ||  id.IsDdbj();
  627. }
  628. const CTextseq_id& CSeq_id_GB_Tree::x_Get(const CSeq_id& id) const
  629. {
  630.     switch ( id.Which() ) {
  631.     case CSeq_id::e_Genbank:
  632.         return id.GetGenbank();
  633.     case CSeq_id::e_Embl:
  634.         return id.GetEmbl();
  635.     case CSeq_id::e_Ddbj:
  636.         return id.GetDdbj();
  637.     default:
  638.         NCBI_THROW(CObjMgrException, eIdMapperError, "Invalid seq-id type");
  639.     }
  640. }
  641. /////////////////////////////////////////////////////////////////////////////
  642. // CSeq_id_Pir_Tree
  643. /////////////////////////////////////////////////////////////////////////////
  644. bool CSeq_id_Pir_Tree::x_Check(const CSeq_id& id) const
  645. {
  646.     return id.IsPir();
  647. }
  648. const CTextseq_id& CSeq_id_Pir_Tree::x_Get(const CSeq_id& id) const
  649. {
  650.     return id.GetPir();
  651. }
  652. /////////////////////////////////////////////////////////////////////////////
  653. // CSeq_id_Swissprot_Tree
  654. /////////////////////////////////////////////////////////////////////////////
  655. bool CSeq_id_Swissprot_Tree::x_Check(const CSeq_id& id) const
  656. {
  657.     return id.IsSwissprot();
  658. }
  659. const CTextseq_id& CSeq_id_Swissprot_Tree::x_Get(const CSeq_id& id) const
  660. {
  661.     return id.GetSwissprot();
  662. }
  663. /////////////////////////////////////////////////////////////////////////////
  664. // CSeq_id_Prf_Tree
  665. /////////////////////////////////////////////////////////////////////////////
  666. bool CSeq_id_Prf_Tree::x_Check(const CSeq_id& id) const
  667. {
  668.     return id.IsPrf();
  669. }
  670. const CTextseq_id& CSeq_id_Prf_Tree::x_Get(const CSeq_id& id) const
  671. {
  672.     return id.GetPrf();
  673. }
  674. /////////////////////////////////////////////////////////////////////////////
  675. // CSeq_id_Tpd_Tree
  676. /////////////////////////////////////////////////////////////////////////////
  677. bool CSeq_id_Tpg_Tree::x_Check(const CSeq_id& id) const
  678. {
  679.     return id.IsTpg();
  680. }
  681. const CTextseq_id& CSeq_id_Tpg_Tree::x_Get(const CSeq_id& id) const
  682. {
  683.     return id.GetTpg();
  684. }
  685. /////////////////////////////////////////////////////////////////////////////
  686. // CSeq_id_Tpe_Tree
  687. /////////////////////////////////////////////////////////////////////////////
  688. bool CSeq_id_Tpe_Tree::x_Check(const CSeq_id& id) const
  689. {
  690.     return id.IsTpe();
  691. }
  692. const CTextseq_id& CSeq_id_Tpe_Tree::x_Get(const CSeq_id& id) const
  693. {
  694.     return id.GetTpe();
  695. }
  696. /////////////////////////////////////////////////////////////////////////////
  697. // CSeq_id_Tpd_Tree
  698. /////////////////////////////////////////////////////////////////////////////
  699. bool CSeq_id_Tpd_Tree::x_Check(const CSeq_id& id) const
  700. {
  701.     return id.IsTpd();
  702. }
  703. const CTextseq_id& CSeq_id_Tpd_Tree::x_Get(const CSeq_id& id) const
  704. {
  705.     return id.GetTpd();
  706. }
  707. /////////////////////////////////////////////////////////////////////////////
  708. // CSeq_id_Other_Tree
  709. /////////////////////////////////////////////////////////////////////////////
  710. bool CSeq_id_Other_Tree::x_Check(const CSeq_id& id) const
  711. {
  712.     return id.IsOther();
  713. }
  714. const CTextseq_id& CSeq_id_Other_Tree::x_Get(const CSeq_id& id) const
  715. {
  716.     return id.GetOther();
  717. }
  718. /////////////////////////////////////////////////////////////////////////////
  719. // CSeq_id_Local_Tree
  720. /////////////////////////////////////////////////////////////////////////////
  721. CSeq_id_Local_Tree::CSeq_id_Local_Tree(void)
  722. {
  723. }
  724. CSeq_id_Local_Tree::~CSeq_id_Local_Tree(void)
  725. {
  726. }
  727. bool CSeq_id_Local_Tree::Empty(void) const
  728. {
  729.     return m_ByStr.empty() && m_ById.empty();
  730. }
  731. CSeq_id_Info* CSeq_id_Local_Tree::x_FindInfo(const CObject_id& oid) const
  732. {
  733.     if ( oid.IsStr() ) {
  734.         TByStr::const_iterator it = m_ByStr.find(oid.GetStr());
  735.         if (it != m_ByStr.end()) {
  736.             return it->second;
  737.         }
  738.     }
  739.     else if ( oid.IsId() ) {
  740.         TById::const_iterator it = m_ById.find(oid.GetId());
  741.         if (it != m_ById.end()) {
  742.             return it->second;
  743.         }
  744.     }
  745.     // Not found
  746.     return 0;
  747. }
  748. CSeq_id_Handle CSeq_id_Local_Tree::FindInfo(const CSeq_id& id) const
  749. {
  750.     _ASSERT( id.IsLocal() );
  751.     const CObject_id& oid = id.GetLocal();
  752.     TReadLockGuard guard(m_TreeLock);
  753.     return CSeq_id_Handle(x_FindInfo(oid));
  754. }
  755. CSeq_id_Handle CSeq_id_Local_Tree::FindOrCreate(const CSeq_id& id)
  756. {
  757.     _ASSERT(id.IsLocal());
  758.     const CObject_id& oid = id.GetLocal();
  759.     TWriteLockGuard guard(m_TreeLock);
  760.     CSeq_id_Info* info = x_FindInfo(oid);
  761.     if ( !info ) {
  762.         info = CreateInfo(id);
  763.         if ( oid.IsStr() ) {
  764.             _VERIFY(m_ByStr.insert(TByStr::value_type(oid.GetStr(),
  765.                                                       info)).second);
  766.         }
  767.         else if ( oid.IsId() ) {
  768.             _VERIFY(m_ById.insert(TById::value_type(oid.GetId(),
  769.                                                     info)).second);
  770.         }
  771.         else {
  772.             NCBI_THROW(CObjMgrException, eIdMapperError,
  773.                        "Can not create index for an empty local seq-id");
  774.         }
  775.     }
  776.     return CSeq_id_Handle(info);
  777. }
  778. void CSeq_id_Local_Tree::x_Unindex(const CSeq_id_Info* info)
  779. {
  780.     CConstRef<CSeq_id> id = info->GetSeqId();
  781.     _ASSERT(id->IsLocal());
  782.     const CObject_id& oid = id->GetLocal();
  783.     if ( oid.IsStr() ) {
  784.         _VERIFY(m_ByStr.erase(oid.GetStr()));
  785.     }
  786.     else if ( oid.IsId() ) {
  787.         _VERIFY(m_ById.erase(oid.GetId()));
  788.     }
  789. }
  790. bool CSeq_id_Local_Tree::HaveMatch(const CSeq_id_Handle& ) const
  791. {
  792.     // Only one entry can match each id
  793.     return false;
  794. }
  795. void CSeq_id_Local_Tree::FindMatch(const CSeq_id_Handle& id,
  796.                                    TSeq_id_MatchList& id_list) const
  797. {
  798.     // Only one entry can match each id
  799.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  800.     id_list.insert(id);
  801. }
  802. void CSeq_id_Local_Tree::FindMatchStr(string sid,
  803.                                       TSeq_id_MatchList& id_list) const
  804. {
  805.     TReadLockGuard guard(m_TreeLock);
  806.     // In any case search in strings
  807.     TByStr::const_iterator str_it = m_ByStr.find(sid);
  808.     if (str_it != m_ByStr.end()) {
  809.         id_list.insert(CSeq_id_Handle(str_it->second));
  810.     }
  811.     else {
  812.         try {
  813.             int value = NStr::StringToInt(sid);
  814.             TById::const_iterator int_it = m_ById.find(value);
  815.             if (int_it != m_ById.end()) {
  816.                 id_list.insert(CSeq_id_Handle(int_it->second));
  817.             }
  818.         }
  819.         catch (const CStringException& /*ignored*/) {
  820.             // Not an integer value
  821.             return;
  822.         }
  823.     }
  824. }
  825. /////////////////////////////////////////////////////////////////////////////
  826. // CSeq_id_General_Tree
  827. /////////////////////////////////////////////////////////////////////////////
  828. CSeq_id_General_Tree::CSeq_id_General_Tree(void)
  829. {
  830. }
  831. CSeq_id_General_Tree::~CSeq_id_General_Tree(void)
  832. {
  833. }
  834. bool CSeq_id_General_Tree::Empty(void) const
  835. {
  836.     return m_DbMap.empty();
  837. }
  838. CSeq_id_Info* CSeq_id_General_Tree::x_FindInfo(const CDbtag& dbid) const
  839. {
  840.     TDbMap::const_iterator db = m_DbMap.find(dbid.GetDb());
  841.     if (db == m_DbMap.end())
  842.         return 0;
  843.     const STagMap& tm = db->second;
  844.     const CObject_id& oid = dbid.GetTag();
  845.     if ( oid.IsStr() ) {
  846.         STagMap::TByStr::const_iterator it = tm.m_ByStr.find(oid.GetStr());
  847.         if (it != tm.m_ByStr.end()) {
  848.             return it->second;
  849.         }
  850.     }
  851.     else if ( oid.IsId() ) {
  852.         STagMap::TById::const_iterator it = tm.m_ById.find(oid.GetId());
  853.         if (it != tm.m_ById.end()) {
  854.             return it->second;
  855.         }
  856.     }
  857.     // Not found
  858.     return 0;
  859. }
  860. CSeq_id_Handle CSeq_id_General_Tree::FindInfo(const CSeq_id& id) const
  861. {
  862.     _ASSERT( id.IsGeneral() );
  863.     const CDbtag& dbid = id.GetGeneral();
  864.     TReadLockGuard guard(m_TreeLock);
  865.     return CSeq_id_Handle(x_FindInfo(dbid));
  866. }
  867. CSeq_id_Handle CSeq_id_General_Tree::FindOrCreate(const CSeq_id& id)
  868. {
  869.     _ASSERT( id.IsGeneral() );
  870.     const CDbtag& dbid = id.GetGeneral();
  871.     TWriteLockGuard guard(m_TreeLock);
  872.     CSeq_id_Info* info = x_FindInfo(dbid);
  873.     if ( !info ) {
  874.         info = CreateInfo(id);
  875.         STagMap& tm = m_DbMap[dbid.GetDb()];
  876.         const CObject_id& oid = dbid.GetTag();
  877.         if ( oid.IsStr() ) {
  878.             _VERIFY(tm.m_ByStr.insert
  879.                     (STagMap::TByStr::value_type(oid.GetStr(), info)).second);
  880.         }
  881.         else if ( oid.IsId() ) {
  882.             _VERIFY(tm.m_ById.insert(STagMap::TById::value_type(oid.GetId(),
  883.                                                                 info)).second);
  884.         }
  885.         else {
  886.             NCBI_THROW(CObjMgrException, eIdMapperError,
  887.                        "Can not create index for an empty db-tag");
  888.         }
  889.     }
  890.     return CSeq_id_Handle(info);
  891. }
  892. void CSeq_id_General_Tree::x_Unindex(const CSeq_id_Info* info)
  893. {
  894.     CConstRef<CSeq_id> id = info->GetSeqId();
  895.     _ASSERT( id->IsGeneral() );
  896.     const CDbtag& dbid = id->GetGeneral();
  897.     TDbMap::iterator db_it = m_DbMap.find(dbid.GetDb());
  898.     _ASSERT(db_it != m_DbMap.end());
  899.     STagMap& tm = db_it->second;
  900.     const CObject_id& oid = dbid.GetTag();
  901.     if ( oid.IsStr() ) {
  902.         _VERIFY(tm.m_ByStr.erase(oid.GetStr()));
  903.     }
  904.     else if ( oid.IsId() ) {
  905.         _VERIFY(tm.m_ById.erase(oid.GetId()));
  906.     }
  907.     if (tm.m_ByStr.empty()  &&  tm.m_ById.empty())
  908.         m_DbMap.erase(db_it);
  909. }
  910. bool CSeq_id_General_Tree::HaveMatch(const CSeq_id_Handle& ) const
  911. {
  912.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  913.     return false;
  914. }
  915. void CSeq_id_General_Tree::FindMatch(const CSeq_id_Handle& id,
  916.                                      TSeq_id_MatchList& id_list) const
  917. {
  918.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  919.     id_list.insert(id);
  920. }
  921. void CSeq_id_General_Tree::FindMatchStr(string sid,
  922.                                         TSeq_id_MatchList& id_list) const
  923. {
  924.     int value;
  925.     bool ok;
  926.     try {
  927.         value = NStr::StringToInt(sid);
  928.         ok = true;
  929.     }
  930.     catch (const CStringException&) {
  931.         // Not an integer value
  932.         value = -1;
  933.         ok = false;
  934.     }
  935.     TReadLockGuard guard(m_TreeLock);
  936.     ITERATE(TDbMap, db_it, m_DbMap) {
  937.         // In any case search in strings
  938.         STagMap::TByStr::const_iterator str_it =
  939.             db_it->second.m_ByStr.find(sid);
  940.         if (str_it != db_it->second.m_ByStr.end()) {
  941.             id_list.insert(CSeq_id_Handle(str_it->second));
  942.         }
  943.         if ( ok ) {
  944.             STagMap::TById::const_iterator int_it =
  945.                 db_it->second.m_ById.find(value);
  946.             if (int_it != db_it->second.m_ById.end()) {
  947.                 id_list.insert(CSeq_id_Handle(int_it->second));
  948.             }
  949.         }
  950.     }
  951. }
  952. /////////////////////////////////////////////////////////////////////////////
  953. // CSeq_id_Giim_Tree
  954. /////////////////////////////////////////////////////////////////////////////
  955. CSeq_id_Giim_Tree::CSeq_id_Giim_Tree(void)
  956. {
  957. }
  958. CSeq_id_Giim_Tree::~CSeq_id_Giim_Tree(void)
  959. {
  960. }
  961. bool CSeq_id_Giim_Tree::Empty(void) const
  962. {
  963.     return m_IdMap.empty();
  964. }
  965. CSeq_id_Info* CSeq_id_Giim_Tree::x_FindInfo(const CGiimport_id& gid) const
  966. {
  967.     TIdMap::const_iterator id_it = m_IdMap.find(gid.GetId());
  968.     if (id_it == m_IdMap.end())
  969.         return 0;
  970.     ITERATE (TGiimList, dbr_it, id_it->second) {
  971.         CConstRef<CSeq_id> id = (*dbr_it)->GetSeqId();
  972.         const CGiimport_id& gid2 = id->GetGiim();
  973.         // Both Db and Release must be equal
  974.         if ( !gid.Equals(gid2) ) {
  975.             return *dbr_it;
  976.         }
  977.     }
  978.     // Not found
  979.     return 0;
  980. }
  981. CSeq_id_Handle CSeq_id_Giim_Tree::FindInfo(const CSeq_id& id) const
  982. {
  983.     _ASSERT( id.IsGiim() );
  984.     const CGiimport_id& gid = id.GetGiim();
  985.     TReadLockGuard guard(m_TreeLock);
  986.     return CSeq_id_Handle(x_FindInfo(gid));
  987. }
  988. CSeq_id_Handle CSeq_id_Giim_Tree::FindOrCreate(const CSeq_id& id)
  989. {
  990.     _ASSERT( id.IsGiim() );
  991.     const CGiimport_id& gid = id.GetGiim();
  992.     TWriteLockGuard guard(m_TreeLock);
  993.     CSeq_id_Info* info = x_FindInfo(gid);
  994.     if ( !info ) {
  995.         info = CreateInfo(id);
  996.         m_IdMap[gid.GetId()].push_back(info);
  997.     }
  998.     return CSeq_id_Handle(info);
  999. }
  1000. void CSeq_id_Giim_Tree::x_Unindex(const CSeq_id_Info* info)
  1001. {
  1002.     CConstRef<CSeq_id> id = info->GetSeqId();
  1003.     _ASSERT( id->IsGiim() );
  1004.     const CGiimport_id& gid = id->GetGiim();
  1005.     TIdMap::iterator id_it = m_IdMap.find(gid.GetId());
  1006.     _ASSERT(id_it != m_IdMap.end());
  1007.     TGiimList& giims = id_it->second;
  1008.     NON_CONST_ITERATE(TGiimList, dbr_it, giims) {
  1009.         if (*dbr_it == info) {
  1010.             giims.erase(dbr_it);
  1011.             break;
  1012.         }
  1013.     }
  1014.     if ( giims.empty() )
  1015.         m_IdMap.erase(id_it);
  1016. }
  1017. bool CSeq_id_Giim_Tree::HaveMatch(const CSeq_id_Handle& ) const
  1018. {
  1019.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  1020.     return false;
  1021. }
  1022. void CSeq_id_Giim_Tree::FindMatch(const CSeq_id_Handle& id,
  1023.                                   TSeq_id_MatchList& id_list) const
  1024. {
  1025.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  1026.     id_list.insert(id);
  1027. }
  1028. void CSeq_id_Giim_Tree::FindMatchStr(string sid,
  1029.                                      TSeq_id_MatchList& id_list) const
  1030. {
  1031.     TReadLockGuard guard(m_TreeLock);
  1032.     try {
  1033.         int value = NStr::StringToInt(sid);
  1034.         TIdMap::const_iterator it = m_IdMap.find(value);
  1035.         if (it == m_IdMap.end())
  1036.             return;
  1037.         ITERATE(TGiimList, git, it->second) {
  1038.             id_list.insert(CSeq_id_Handle(*git));
  1039.         }
  1040.     }
  1041.     catch (CStringException) {
  1042.         // Not an integer value
  1043.         return;
  1044.     }
  1045. }
  1046. /////////////////////////////////////////////////////////////////////////////
  1047. // CSeq_id_Patent_Tree
  1048. /////////////////////////////////////////////////////////////////////////////
  1049. CSeq_id_Patent_Tree::CSeq_id_Patent_Tree(void)
  1050. {
  1051. }
  1052. CSeq_id_Patent_Tree::~CSeq_id_Patent_Tree(void)
  1053. {
  1054. }
  1055. bool CSeq_id_Patent_Tree::Empty(void) const
  1056. {
  1057.     return m_CountryMap.empty();
  1058. }
  1059. CSeq_id_Info* CSeq_id_Patent_Tree::x_FindInfo(const CPatent_seq_id& pid) const
  1060. {
  1061.     const CId_pat& cit = pid.GetCit();
  1062.     TByCountry::const_iterator cntry_it = m_CountryMap.find(cit.GetCountry());
  1063.     if (cntry_it == m_CountryMap.end())
  1064.         return 0;
  1065.     const string* number;
  1066.     const SPat_idMap::TByNumber* by_number;
  1067.     if ( cit.GetId().IsNumber() ) {
  1068.         number = &cit.GetId().GetNumber();
  1069.         by_number = &cntry_it->second.m_ByNumber;
  1070.     }
  1071.     else if ( cit.GetId().IsApp_number() ) {
  1072.         number = &cit.GetId().GetApp_number();
  1073.         by_number = &cntry_it->second.m_ByApp_number;
  1074.     }
  1075.     else {
  1076.         return 0;
  1077.     }
  1078.     SPat_idMap::TByNumber::const_iterator num_it = by_number->find(*number);
  1079.     if (num_it == by_number->end())
  1080.         return 0;
  1081.     SPat_idMap::TBySeqid::const_iterator seqid_it =
  1082.         num_it->second.find(pid.GetSeqid());
  1083.     if (seqid_it != num_it->second.end()) {
  1084.         return seqid_it->second;
  1085.     }
  1086.     // Not found
  1087.     return 0;
  1088. }
  1089. CSeq_id_Handle CSeq_id_Patent_Tree::FindInfo(const CSeq_id& id) const
  1090. {
  1091.     _ASSERT( id.IsPatent() );
  1092.     const CPatent_seq_id& pid = id.GetPatent();
  1093.     TReadLockGuard guard(m_TreeLock);
  1094.     return CSeq_id_Handle(x_FindInfo(pid));
  1095. }
  1096. CSeq_id_Handle CSeq_id_Patent_Tree::FindOrCreate(const CSeq_id& id)
  1097. {
  1098.     _ASSERT( id.IsPatent() );
  1099.     const CPatent_seq_id& pid = id.GetPatent();
  1100.     TWriteLockGuard guard(m_TreeLock);
  1101.     CSeq_id_Info* info = x_FindInfo(pid);
  1102.     if ( !info ) {
  1103.         const CId_pat& cit = pid.GetCit();
  1104.         SPat_idMap& country = m_CountryMap[cit.GetCountry()];
  1105.         if ( cit.GetId().IsNumber() ) {
  1106.             SPat_idMap::TBySeqid& num =
  1107.                 country.m_ByNumber[cit.GetId().GetNumber()];
  1108.             _ASSERT(num.find(pid.GetSeqid()) == num.end());
  1109.             info = CreateInfo(id);
  1110.             num[pid.GetSeqid()] = info;
  1111.         }
  1112.         else if ( cit.GetId().IsApp_number() ) {
  1113.             SPat_idMap::TBySeqid& app = country.m_ByApp_number[
  1114.                 cit.GetId().GetApp_number()];
  1115.             _ASSERT(app.find(pid.GetSeqid()) == app.end());
  1116.             info = CreateInfo(id);
  1117.             app[pid.GetSeqid()] = info;
  1118.         }
  1119.         else {
  1120.             // Can not index empty patent number
  1121.             NCBI_THROW(CObjMgrException, eIdMapperError,
  1122.                        "Cannot index empty patent number");
  1123.         }
  1124.     }
  1125.     return CSeq_id_Handle(info);
  1126. }
  1127. void CSeq_id_Patent_Tree::x_Unindex(const CSeq_id_Info* info)
  1128. {
  1129.     CConstRef<CSeq_id> id = info->GetSeqId();
  1130.     _ASSERT( id->IsPatent() );
  1131.     const CPatent_seq_id& pid = id->GetPatent();
  1132.     TByCountry::iterator country_it =
  1133.         m_CountryMap.find(pid.GetCit().GetCountry());
  1134.     _ASSERT(country_it != m_CountryMap.end());
  1135.     SPat_idMap& pats = country_it->second;
  1136.     if ( pid.GetCit().GetId().IsNumber() ) {
  1137.         SPat_idMap::TByNumber::iterator num_it =
  1138.             pats.m_ByNumber.find(pid.GetCit().GetId().GetNumber());
  1139.         _ASSERT(num_it != pats.m_ByNumber.end());
  1140.         SPat_idMap::TBySeqid::iterator seqid_it =
  1141.             num_it->second.find(pid.GetSeqid());
  1142.         _ASSERT(seqid_it != num_it->second.end());
  1143.         _ASSERT(seqid_it->second == info);
  1144.         num_it->second.erase(seqid_it);
  1145.         if ( num_it->second.empty() )
  1146.             pats.m_ByNumber.erase(num_it);
  1147.     }
  1148.     else if ( pid.GetCit().GetId().IsApp_number() ) {
  1149.         SPat_idMap::TByNumber::iterator app_it =
  1150.             pats.m_ByApp_number.find(pid.GetCit().GetId().GetApp_number());
  1151.         _ASSERT(app_it == pats.m_ByApp_number.end());
  1152.         SPat_idMap::TBySeqid::iterator seqid_it =
  1153.             app_it->second.find(pid.GetSeqid());
  1154.         _ASSERT(seqid_it != app_it->second.end());
  1155.         _ASSERT(seqid_it->second == info);
  1156.         app_it->second.erase(seqid_it);
  1157.         if ( app_it->second.empty() )
  1158.             pats.m_ByNumber.erase(app_it);
  1159.     }
  1160.     if (country_it->second.m_ByNumber.empty()  &&
  1161.         country_it->second.m_ByApp_number.empty())
  1162.         m_CountryMap.erase(country_it);
  1163. }
  1164. bool CSeq_id_Patent_Tree::HaveMatch(const CSeq_id_Handle& ) const
  1165. {
  1166.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  1167.     return false;
  1168. }
  1169. void CSeq_id_Patent_Tree::FindMatch(const CSeq_id_Handle& id,
  1170.                                     TSeq_id_MatchList& id_list) const
  1171. {
  1172.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  1173.     id_list.insert(id);
  1174. }
  1175. void CSeq_id_Patent_Tree::FindMatchStr(string sid,
  1176.                                        TSeq_id_MatchList& id_list) const
  1177. {
  1178.     TReadLockGuard guard(m_TreeLock);
  1179.     ITERATE (TByCountry, cit, m_CountryMap) {
  1180.         SPat_idMap::TByNumber::const_iterator nit =
  1181.             cit->second.m_ByNumber.find(sid);
  1182.         if (nit != cit->second.m_ByNumber.end()) {
  1183.             ITERATE(SPat_idMap::TBySeqid, iit, nit->second) {
  1184.                 id_list.insert(CSeq_id_Handle(iit->second));
  1185.             }
  1186.         }
  1187.         SPat_idMap::TByNumber::const_iterator ait =
  1188.             cit->second.m_ByApp_number.find(sid);
  1189.         if (ait != cit->second.m_ByApp_number.end()) {
  1190.             ITERATE(SPat_idMap::TBySeqid, iit, nit->second) {
  1191.                 id_list.insert(CSeq_id_Handle(iit->second));
  1192.             }
  1193.         }
  1194.     }
  1195. }
  1196. /////////////////////////////////////////////////////////////////////////////
  1197. // CSeq_id_PDB_Tree
  1198. /////////////////////////////////////////////////////////////////////////////
  1199. CSeq_id_PDB_Tree::CSeq_id_PDB_Tree(void)
  1200. {
  1201. }
  1202. CSeq_id_PDB_Tree::~CSeq_id_PDB_Tree(void)
  1203. {
  1204. }
  1205. bool CSeq_id_PDB_Tree::Empty(void) const
  1206. {
  1207.     return m_MolMap.empty();
  1208. }
  1209. inline string CSeq_id_PDB_Tree::x_IdToStrKey(const CPDB_seq_id& id) const
  1210. {
  1211. // this is an attempt to follow the undocumented rules of PDB
  1212. // ("documented" as code written elsewhere)
  1213.     string skey = id.GetMol().Get();
  1214.     switch (char chain = (char)id.GetChain()) {
  1215.     case '': skey += " ";   break;
  1216.     case '|':  skey += "VB";  break;
  1217.     default:   skey += chain; break;
  1218.     }
  1219.     return skey;
  1220. }
  1221. CSeq_id_Info* CSeq_id_PDB_Tree::x_FindInfo(const CPDB_seq_id& pid) const
  1222. {
  1223.     TMolMap::const_iterator mol_it = m_MolMap.find(x_IdToStrKey(pid));
  1224.     if (mol_it == m_MolMap.end())
  1225.         return 0;
  1226.     ITERATE(TSubMolList, it, mol_it->second) {
  1227.         CConstRef<CSeq_id> id = (*it)->GetSeqId();
  1228.         if (pid.Equals(id->GetPdb())) {
  1229.             return *it;
  1230.         }
  1231.     }
  1232.     // Not found
  1233.     return 0;
  1234. }
  1235. CSeq_id_Handle CSeq_id_PDB_Tree::FindInfo(const CSeq_id& id) const
  1236. {
  1237.     _ASSERT( id.IsPdb() );
  1238.     const CPDB_seq_id& pid = id.GetPdb();
  1239.     TReadLockGuard guard(m_TreeLock);
  1240.     return CSeq_id_Handle(x_FindInfo(pid));
  1241. }
  1242. CSeq_id_Handle CSeq_id_PDB_Tree::FindOrCreate(const CSeq_id& id)
  1243. {
  1244.     _ASSERT( id.IsPdb() );
  1245.     const CPDB_seq_id& pid = id.GetPdb();
  1246.     TWriteLockGuard guard(m_TreeLock);
  1247.     CSeq_id_Info* info = x_FindInfo(pid);
  1248.     if ( !info ) {
  1249.         info = CreateInfo(id);
  1250.         TSubMolList& sub = m_MolMap[x_IdToStrKey(id.GetPdb())];
  1251.         ITERATE(TSubMolList, sub_it, sub) {
  1252.             _ASSERT(!info->GetSeqId()->GetPdb()
  1253.                     .Equals((*sub_it)->GetSeqId()->GetPdb()));
  1254.         }
  1255.         sub.push_back(info);
  1256.     }
  1257.     return CSeq_id_Handle(info);
  1258. }
  1259. void CSeq_id_PDB_Tree::x_Unindex(const CSeq_id_Info* info)
  1260. {
  1261.     CConstRef<CSeq_id> id = info->GetSeqId();
  1262.     _ASSERT( id->IsPdb() );
  1263.     const CPDB_seq_id& pid = id->GetPdb();
  1264.     TMolMap::iterator mol_it = m_MolMap.find(x_IdToStrKey(pid));
  1265.     _ASSERT(mol_it != m_MolMap.end());
  1266.     NON_CONST_ITERATE(TSubMolList, it, mol_it->second) {
  1267.         if (*it == info) {
  1268.             CConstRef<CSeq_id> id2 = (*it)->GetSeqId();
  1269.             _ASSERT(pid.Equals(id2->GetPdb()));
  1270.             mol_it->second.erase(it);
  1271.             break;
  1272.         }
  1273.     }
  1274.     if ( mol_it->second.empty() )
  1275.         m_MolMap.erase(mol_it);
  1276. }
  1277. void CSeq_id_PDB_Tree::FindMatch(const CSeq_id_Handle& id,
  1278.                                  TSeq_id_MatchList& id_list) const
  1279. {
  1280.     //_ASSERT(id && id == FindInfo(id.GetSeqId()));
  1281.     CConstRef<CSeq_id> seq_id = id.GetSeqId();
  1282.     const CPDB_seq_id& pid = seq_id->GetPdb();
  1283.     TReadLockGuard guard(m_TreeLock);
  1284.     TMolMap::const_iterator mol_it = m_MolMap.find(x_IdToStrKey(pid));
  1285.     if (mol_it == m_MolMap.end())
  1286.         return;
  1287.     ITERATE(TSubMolList, it, mol_it->second) {
  1288.         CConstRef<CSeq_id> seq_id2 = (*it)->GetSeqId();
  1289.         const CPDB_seq_id& pid2 = seq_id2->GetPdb();
  1290.         // Ignore date if not set in id
  1291.         if ( pid.IsSetRel() ) {
  1292.             if ( !pid2.IsSetRel()  ||
  1293.                 !pid.GetRel().Equals(pid2.GetRel()) )
  1294.                 continue;
  1295.         }
  1296.         id_list.insert(CSeq_id_Handle(*it));
  1297.     }
  1298. }
  1299. void CSeq_id_PDB_Tree::FindMatchStr(string sid,
  1300.                                     TSeq_id_MatchList& id_list) const
  1301. {
  1302.     TReadLockGuard guard(m_TreeLock);
  1303.     TMolMap::const_iterator mit = m_MolMap.find(sid);
  1304.     if (mit == m_MolMap.end())
  1305.         return;
  1306.     ITERATE(TSubMolList, sub_it, mit->second) {
  1307.         id_list.insert(CSeq_id_Handle(*sub_it));
  1308.     }
  1309. }
  1310. END_SCOPE(objects)
  1311. END_NCBI_SCOPE
  1312. /*
  1313. * ---------------------------------------------------------------------------
  1314. * $Log: seq_id_tree.cpp,v $
  1315. * Revision 1000.4  2004/06/01 19:24:07  gouriano
  1316. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  1317. *
  1318. * Revision 1.13  2004/05/21 21:42:13  gorelenk
  1319. * Added PCH ncbi_pch.hpp
  1320. *
  1321. * Revision 1.12  2004/04/29 13:17:51  grichenk
  1322. * Fixed reverse ID matching
  1323. *
  1324. * Revision 1.11  2004/04/21 19:55:05  grichenk
  1325. * Fixed textseq-id matching.
  1326. *
  1327. * Revision 1.10  2004/04/21 13:37:13  grichenk
  1328. * Fixed reverse matching IDs
  1329. *
  1330. * Revision 1.9  2004/02/19 17:53:09  vasilche
  1331. * Explicit creation of CSeq_id_Handle.
  1332. *
  1333. * Revision 1.8  2004/02/19 17:25:35  vasilche
  1334. * Use CRef<> to safely hold pointer to CSeq_id_Info.
  1335. * CSeq_id_Info holds pointer to owner CSeq_id_Which_Tree.
  1336. * Reduce number of calls to CSeq_id_Handle.GetSeqId().
  1337. *
  1338. * Revision 1.7  2004/02/10 21:15:16  grichenk
  1339. * Added reverse ID matching.
  1340. *
  1341. * Revision 1.6  2004/02/09 14:41:50  vasilche
  1342. * Fixed processing of version & release in Textseq-id.
  1343. *
  1344. * Revision 1.5  2004/01/07 20:42:02  grichenk
  1345. * Fixed matching of accession to accession.version
  1346. *
  1347. * Revision 1.4  2003/09/30 16:22:03  vasilche
  1348. * Updated internal object manager classes to be able to load ID2 data.
  1349. * SNP blobs are loaded as ID2 split blobs - readers convert them automatically.
  1350. * Scope caches results of requests for data to data loaders.
  1351. * Optimized CSeq_id_Handle for gis.
  1352. * Optimized bioseq lookup in scope.
  1353. * Reduced object allocations in annotation iterators.
  1354. * CScope is allowed to be destroyed before other objects using this scope are
  1355. * deleted (feature iterators, bioseq handles etc).
  1356. * Optimized lookup for matching Seq-ids in CSeq_id_Mapper.
  1357. * Added 'adaptive' option to objmgr_demo application.
  1358. *
  1359. * Revision 1.3  2003/09/05 17:29:40  grichenk
  1360. * Structurized Object Manager exceptions
  1361. *
  1362. * Revision 1.2  2003/06/30 18:40:04  vasilche
  1363. * Fixed warning (unused argument).
  1364. *
  1365. * Revision 1.1  2003/06/10 19:06:35  vasilche
  1366. * Simplified CSeq_id_Mapper and CSeq_id_Handle.
  1367. *
  1368. *
  1369. * ===========================================================================
  1370. */