1 /* $Id: seq_id_mapper.cpp 430230 2014-03-24 20:35:20Z grichenk $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Aleksey Grichenko, Eugene Vasilchenko
27 *
28 * File Description:
29 * Seq-id mapper for Object Manager
30 *
31 */
32
33 #include <ncbi_pch.hpp>
34 #include <objects/seq/seq_id_mapper.hpp>
35 #include <corelib/ncbimtx.hpp>
36 #include "seq_id_tree.hpp"
37
38 BEGIN_NCBI_SCOPE
39 BEGIN_SCOPE(objects)
40
41 ////////////////////////////////////////////////////////////////////
42 //
43 // CSeq_id_Mapper::
44 //
45
46
47 typedef CSeq_id_Mapper TInstance;
48
49 // slow implementation with mutex
50 static TInstance* s_Instance = 0;
51 DEFINE_STATIC_FAST_MUTEX(s_InstanceMutex);
52
GetInstance(void)53 CRef<TInstance> TInstance::GetInstance(void)
54 {
55 CRef<TInstance> ret;
56 {{
57 CFastMutexGuard guard(s_InstanceMutex);
58 ret.Reset(s_Instance);
59 if ( !ret || ret->ReferencedOnlyOnce() ) {
60 if ( ret ) {
61 ret.Release();
62 }
63 ret.Reset(new TInstance);
64 s_Instance = ret;
65 }
66 }}
67 _ASSERT(ret == s_Instance);
68 return ret;
69 }
70
71
s_ResetInstance(TInstance * instance)72 static void s_ResetInstance(TInstance* instance)
73 {
74 CFastMutexGuard guard(s_InstanceMutex);
75 if ( s_Instance == instance ) {
76 s_Instance = 0;
77 }
78 }
79
80
CSeq_id_Mapper(void)81 CSeq_id_Mapper::CSeq_id_Mapper(void)
82 {
83 CSeq_id_Which_Tree::Initialize(this, m_Trees);
84 }
85
86
~CSeq_id_Mapper(void)87 CSeq_id_Mapper::~CSeq_id_Mapper(void)
88 {
89 s_ResetInstance(this);
90 ITERATE ( TTrees, it, m_Trees ) {
91 _ASSERT((*it)->Empty());
92 }
93 }
94
95
96 inline
x_GetTree(const CSeq_id_Handle & idh)97 CSeq_id_Which_Tree& CSeq_id_Mapper::x_GetTree(const CSeq_id_Handle& idh)
98 {
99 CSeq_id::E_Choice type;
100 if ( !idh ) {
101 type = CSeq_id::e_not_set;
102 }
103 else if ( idh.IsGi() ) {
104 type = CSeq_id::e_Gi;
105 }
106 else {
107 return idh.m_Info->GetTree();
108 }
109 _ASSERT(size_t(type) < m_Trees.size());
110 return *m_Trees[type];
111 }
112
113
GetGiHandle(TGi gi)114 CSeq_id_Handle CSeq_id_Mapper::GetGiHandle(TGi gi)
115 {
116 _ASSERT(size_t(CSeq_id::e_Gi) < m_Trees.size());
117 return m_Trees[CSeq_id::e_Gi]->GetGiHandle(gi);
118 }
119
120
GetHandle(const CSeq_id & id,bool do_not_create)121 CSeq_id_Handle CSeq_id_Mapper::GetHandle(const CSeq_id& id, bool do_not_create)
122 {
123 CSeq_id_Which_Tree& tree = x_GetTree(id);
124 return do_not_create? tree.FindInfo(id): tree.FindOrCreate(id);
125 }
126
127
HaveMatchingHandles(const CSeq_id_Handle & idh)128 bool CSeq_id_Mapper::HaveMatchingHandles(const CSeq_id_Handle& idh)
129 {
130 return x_GetTree(idh).HaveMatch(idh);
131 }
132
133
GetMatchingHandles(const CSeq_id_Handle & idh,TSeq_id_HandleSet & h_set)134 void CSeq_id_Mapper::GetMatchingHandles(const CSeq_id_Handle& idh,
135 TSeq_id_HandleSet& h_set)
136 {
137 x_GetTree(idh).FindMatch(idh, h_set);
138 }
139
140
HaveReverseMatch(const CSeq_id_Handle & idh)141 bool CSeq_id_Mapper::HaveReverseMatch(const CSeq_id_Handle& idh)
142 {
143 return x_GetTree(idh).HaveReverseMatch(idh);
144 }
145
146
GetReverseMatchingHandles(const CSeq_id_Handle & idh,TSeq_id_HandleSet & h_set)147 void CSeq_id_Mapper::GetReverseMatchingHandles(const CSeq_id_Handle& idh,
148 TSeq_id_HandleSet& h_set)
149 {
150 x_GetTree(idh).FindReverseMatch(idh, h_set);
151 }
152
153
HaveMatchingHandles(const CSeq_id_Handle & idh,EAllowWeakMatch allow_weak_match)154 bool CSeq_id_Mapper::HaveMatchingHandles(const CSeq_id_Handle& idh,
155 EAllowWeakMatch allow_weak_match)
156 {
157 if ( HaveMatchingHandles(idh) ) {
158 return true;
159 }
160 if ( allow_weak_match == eNoWeakMatch ) {
161 return false;
162 }
163 const CSeq_id_Which_Tree* base_tree = &x_GetTree(idh);
164 if ( !dynamic_cast<const CSeq_id_Textseq_Tree*>(base_tree) ) {
165 return false;
166 }
167 for ( size_t i = 0; i < m_Trees.size(); ++i ) {
168 const CSeq_id_Which_Tree* tree = m_Trees[i];
169 if ( tree == base_tree ) {
170 continue;
171 }
172 if ( !dynamic_cast<const CSeq_id_Textseq_Tree*>(tree) ) {
173 continue;
174 }
175 if ( tree == m_Trees[CSeq_id::e_Gi] && i != CSeq_id::e_Gi ) {
176 continue;
177 }
178 if ( tree->HaveMatch(idh) ) {
179 return true;
180 }
181 }
182 return false;
183 }
184
185
GetMatchingHandles(const CSeq_id_Handle & idh,TSeq_id_HandleSet & h_set,EAllowWeakMatch allow_weak_match)186 void CSeq_id_Mapper::GetMatchingHandles(const CSeq_id_Handle& idh,
187 TSeq_id_HandleSet& h_set,
188 EAllowWeakMatch allow_weak_match)
189 {
190 GetMatchingHandles(idh, h_set);
191 if ( allow_weak_match == eNoWeakMatch ) {
192 return;
193 }
194 const CSeq_id_Which_Tree* base_tree = &x_GetTree(idh);
195 if ( !dynamic_cast<const CSeq_id_Textseq_Tree*>(base_tree) ) {
196 return;
197 }
198 for ( size_t i = 0; i < m_Trees.size(); ++i ) {
199 const CSeq_id_Which_Tree* tree = m_Trees[i];
200 if ( tree == base_tree ) {
201 continue;
202 }
203 if ( !dynamic_cast<const CSeq_id_Textseq_Tree*>(tree) ) {
204 continue;
205 }
206 if ( tree == m_Trees[CSeq_id::e_Gi] && i != CSeq_id::e_Gi ) {
207 continue;
208 }
209 tree->FindMatch(idh, h_set);
210 }
211 }
212
213
HaveReverseMatch(const CSeq_id_Handle & idh,EAllowWeakMatch allow_weak_match)214 bool CSeq_id_Mapper::HaveReverseMatch(const CSeq_id_Handle& idh,
215 EAllowWeakMatch allow_weak_match)
216 {
217 if ( HaveReverseMatch(idh) ) {
218 return true;
219 }
220 if ( allow_weak_match == eNoWeakMatch ) {
221 return false;
222 }
223 const CSeq_id_Which_Tree* base_tree = &x_GetTree(idh);
224 if ( !dynamic_cast<const CSeq_id_Textseq_Tree*>(base_tree) ) {
225 return false;
226 }
227 for ( size_t i = 0; i < m_Trees.size(); ++i ) {
228 const CSeq_id_Which_Tree* tree = m_Trees[i];
229 if ( tree == base_tree ) {
230 continue;
231 }
232 if ( !dynamic_cast<const CSeq_id_Textseq_Tree*>(tree) ) {
233 continue;
234 }
235 if ( tree == m_Trees[CSeq_id::e_Gi] && i != CSeq_id::e_Gi ) {
236 continue;
237 }
238 if ( tree->HaveReverseMatch(idh) ) {
239 return true;
240 }
241 }
242 return false;
243 }
244
245
GetReverseMatchingHandles(const CSeq_id_Handle & idh,TSeq_id_HandleSet & h_set,EAllowWeakMatch allow_weak_match)246 void CSeq_id_Mapper::GetReverseMatchingHandles(const CSeq_id_Handle& idh,
247 TSeq_id_HandleSet& h_set,
248 EAllowWeakMatch allow_weak_match)
249 {
250 GetReverseMatchingHandles(idh, h_set);
251 if ( allow_weak_match == eNoWeakMatch ) {
252 return;
253 }
254 const CSeq_id_Which_Tree* base_tree = &x_GetTree(idh);
255 if ( !dynamic_cast<const CSeq_id_Textseq_Tree*>(base_tree) ) {
256 return;
257 }
258 for ( size_t i = 0; i < m_Trees.size(); ++i ) {
259 CSeq_id_Which_Tree* tree = m_Trees[i];
260 if ( tree == base_tree ) {
261 continue;
262 }
263 if ( !dynamic_cast<const CSeq_id_Textseq_Tree*>(tree) ) {
264 continue;
265 }
266 if ( tree == m_Trees[CSeq_id::e_Gi] && i != CSeq_id::e_Gi ) {
267 continue;
268 }
269 tree->FindReverseMatch(idh, h_set);
270 }
271 }
272
273
GetMatchingHandlesStr(string sid,TSeq_id_HandleSet & h_set)274 void CSeq_id_Mapper::GetMatchingHandlesStr(string sid,
275 TSeq_id_HandleSet& h_set)
276 {
277 if (sid.find('|') != string::npos) {
278 NCBI_THROW(CSeq_id_MapperException, eSymbolError,
279 "Symbol \'|\' is not supported here");
280 }
281
282 ITERATE(TTrees, tree_it, m_Trees) {
283 (*tree_it)->FindMatchStr(sid, h_set);
284 }
285 }
286
287
x_Match(const CSeq_id_Handle & h1,const CSeq_id_Handle & h2)288 bool CSeq_id_Mapper::x_Match(const CSeq_id_Handle& h1,
289 const CSeq_id_Handle& h2)
290 {
291 CSeq_id_Which_Tree& tree1 = x_GetTree(h1);
292 CSeq_id_Which_Tree& tree2 = x_GetTree(h2);
293 if ( &tree1 != &tree2 )
294 return false;
295
296 // Compare versions if any
297 return tree1.Match(h1, h2);
298 }
299
300
x_IsBetter(const CSeq_id_Handle & h1,const CSeq_id_Handle & h2)301 bool CSeq_id_Mapper::x_IsBetter(const CSeq_id_Handle& h1,
302 const CSeq_id_Handle& h2)
303 {
304 CSeq_id_Which_Tree& tree1 = x_GetTree(h1);
305 CSeq_id_Which_Tree& tree2 = x_GetTree(h2);
306 if ( &tree1 != &tree2 )
307 return false;
308
309 // Compare versions if any
310 return tree1.IsBetterVersion(h1, h2);
311 }
312
313
Dump(CNcbiOstream & out,EDumpDetails details) const314 size_t CSeq_id_Mapper::Dump(CNcbiOstream& out, EDumpDetails details) const
315 {
316 size_t total_bytes = 0;
317 for ( size_t i = 0; i < m_Trees.size(); ++i ) {
318 size_t bytes = m_Trees[i]->Dump(out, CSeq_id::E_Choice(i), details);
319 total_bytes += bytes;
320 }
321 if ( details >= eDumpTotalBytes ) {
322 out << "Total CSeq_id_Mapper bytes: "<<total_bytes<<endl;
323 }
324 return total_bytes;
325 }
326
327
328 END_SCOPE(objects)
329 END_NCBI_SCOPE
330