1 #ifndef OBJECTS_OBJMGR___SEQ_ID_HANDLE__HPP
2 #define OBJECTS_OBJMGR___SEQ_ID_HANDLE__HPP
3
4 /* $Id: seq_id_handle.hpp 602775 2020-03-02 19:52:55Z grichenk $
5 * ===========================================================================
6 *
7 * PUBLIC DOMAIN NOTICE
8 * National Center for Biotechnology Information
9 *
10 * This software/database is a "United States Government Work" under the
11 * terms of the United States Copyright Act. It was written as part of
12 * the author's official duties as a United States Government employee and
13 * thus cannot be copyrighted. This software/database is freely available
14 * to the public for use. The National Library of Medicine and the U.S.
15 * Government have not placed any restriction on its use or reproduction.
16 *
17 * Although all reasonable efforts have been taken to ensure the accuracy
18 * and reliability of the software and data, the NLM and the U.S.
19 * Government do not and cannot warrant the performance or results that
20 * may be obtained by using this software or data. The NLM and the U.S.
21 * Government disclaim all warranties, express or implied, including
22 * warranties of performance, merchantability or fitness for any particular
23 * purpose.
24 *
25 * Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Author: Aleksey Grichenko, Eugene Vasilchenko
30 *
31 * File Description:
32 * Seq-id handle for Object Manager
33 *
34 */
35
36
37 #include <objects/seqloc/Seq_id.hpp>
38
39 #include <set>
40 #include <vector>
41
42 BEGIN_NCBI_SCOPE
43 BEGIN_SCOPE(objects)
44
45 /** @addtogroup OBJECTS_Seqid
46 *
47 * @{
48 */
49
50
51 /////////////////////////////////////////////////////////////////////
52 ///
53 /// CSeq_id_Handle::
54 ///
55 /// Handle to be used instead of CSeq_id. Supports different
56 /// methods of comparison: exact equality or match of seq-ids.
57 ///
58
59 // forward declaration
60 class CSeq_id;
61 class CSeq_id_Handle;
62 class CSeq_id_Mapper;
63 class CSeq_id_Which_Tree;
64
65
66 class CSeq_id_Info : public CObject
67 {
68 public:
69 typedef TIntId TPacked;
70 typedef Uint8 TVariant;
71
72 NCBI_SEQ_EXPORT CSeq_id_Info(CSeq_id::E_Choice type,
73 CSeq_id_Mapper* mapper);
74 NCBI_SEQ_EXPORT CSeq_id_Info(const CConstRef<CSeq_id>& seq_id,
75 CSeq_id_Mapper* mapper);
76 NCBI_SEQ_EXPORT ~CSeq_id_Info(void);
77
GetSeqId(void) const78 CConstRef<CSeq_id> GetSeqId(void) const
79 {
80 return m_Seq_id;
81 }
82 NCBI_SEQ_EXPORT virtual CConstRef<CSeq_id> GetPackedSeqId(TPacked packed, TVariant variant) const;
83
84 // locking
AddLock(void) const85 void AddLock(void) const
86 {
87 m_LockCounter.Add(1);
88 }
RemoveLock(void) const89 void RemoveLock(void) const
90 {
91 if ( m_LockCounter.Add(-1) <= 0 ) {
92 x_RemoveLastLock();
93 }
94 }
IsLocked(void) const95 bool IsLocked(void) const
96 {
97 return m_LockCounter.Get() != 0;
98 }
99
GetType(void) const100 CSeq_id::E_Choice GetType(void) const
101 {
102 return m_Seq_id_Type;
103 }
GetMapper(void) const104 CSeq_id_Mapper& GetMapper(void) const
105 {
106 return *m_Mapper;
107 }
108 NCBI_SEQ_EXPORT CSeq_id_Which_Tree& GetTree(void) const;
109
110 protected:
111 friend class CSeq_id_Which_Tree;
112
113 NCBI_SEQ_EXPORT void x_RemoveLastLock(void) const;
114
115 mutable CAtomicCounter_WithAutoInit m_LockCounter;
116 CSeq_id::E_Choice m_Seq_id_Type;
117 CConstRef<CSeq_id> m_Seq_id;
118 mutable CRef<CSeq_id_Mapper> m_Mapper;
119
120 private:
121 // to prevent copying
122 CSeq_id_Info(const CSeq_id_Info&);
123 const CSeq_id_Info& operator=(const CSeq_id_Info&);
124 };
125
126
127 class CSeq_id_InfoLocker : public CObjectCounterLocker
128 {
129 public:
Lock(const CSeq_id_Info * info) const130 void Lock(const CSeq_id_Info* info) const
131 {
132 CObjectCounterLocker::Lock(info);
133 info->AddLock();
134 }
Relock(const CSeq_id_Info * info) const135 void Relock(const CSeq_id_Info* info) const
136 {
137 Lock(info);
138 }
Unlock(const CSeq_id_Info * info) const139 void Unlock(const CSeq_id_Info* info) const
140 {
141 info->RemoveLock();
142 CObjectCounterLocker::Unlock(info);
143 }
144 };
145
146
147 enum EAllowWeakMatch {
148 eNoWeakMatch,
149 eAllowWeakMatch
150 };
151
152
153 class CSeq_id_Handle
154 {
155 public:
156 typedef CSeq_id_Info::TPacked TPacked;
157 typedef CSeq_id_Info::TVariant TVariant;
158
159 // 'ctors
CSeq_id_Handle(void)160 CSeq_id_Handle(void)
161 : m_Info(null), m_Packed(0), m_Variant(0)
162 {
163 }
CSeq_id_Handle(const CSeq_id_Info * info,TPacked packed=0,TVariant variant=0)164 explicit CSeq_id_Handle(const CSeq_id_Info* info, TPacked packed = 0, TVariant variant = 0)
165 : m_Info(info), m_Packed(packed), m_Variant(variant)
166 {
167 _ASSERT(info || (!packed && !variant));
168 }
CSeq_id_Handle(ENull)169 CSeq_id_Handle(ENull /*null*/)
170 : m_Info(null), m_Packed(0), m_Variant(0)
171 {
172 }
173
174 /// Normal way of getting a handle, works for any seq-id.
175 static NCBI_SEQ_EXPORT CSeq_id_Handle GetHandle(const CSeq_id& id);
176
177 /// Construct CSeq_id from string representation and return handle for it.
178 static NCBI_SEQ_EXPORT CSeq_id_Handle GetHandle(const string& str_id);
179
180 /// Faster way to create a handle for a gi.
181 static NCBI_SEQ_EXPORT CSeq_id_Handle GetHandle(TGi gi);
182
183 /// Faster way to create a handle for a gi.
GetGiHandle(TGi gi)184 static CSeq_id_Handle GetGiHandle(TGi gi)
185 {
186 return GetHandle(gi);
187 }
188
operator ==(const CSeq_id_Handle & handle) const189 bool operator== (const CSeq_id_Handle& handle) const
190 {
191 return m_Packed == handle.m_Packed && m_Info == handle.m_Info;
192 }
operator !=(const CSeq_id_Handle & handle) const193 bool operator!= (const CSeq_id_Handle& handle) const
194 {
195 return m_Packed != handle.m_Packed || m_Info != handle.m_Info;
196 }
operator <(const CSeq_id_Handle & handle) const197 bool operator< (const CSeq_id_Handle& handle) const
198 {
199 // Packed (m_Packed != 0) first:
200 // zeroes are converted to a highest unsigned value by decrement.
201 TUintId p1 = INT_ID_TO(TUintId, m_Packed-1);
202 TUintId p2 = INT_ID_TO(TUintId, handle.m_Packed-1);
203 return p1 < p2 || (p1 == p2 && m_Info < handle.m_Info);
204 }
205 bool NCBI_SEQ_EXPORT operator== (const CSeq_id& id) const;
206
207 /// Compare ids in a defined order (see CSeq_id::CompareOrdered())
208 int NCBI_SEQ_EXPORT CompareOrdered(const CSeq_id_Handle& id) const;
209 /// Predicate for sorting CSeq_id_Handles in a defined order.
210 struct PLessOrdered
211 {
operator ()CSeq_id_Handle::PLessOrdered212 bool operator()(const CSeq_id_Handle& id1,
213 const CSeq_id_Handle& id2) const
214 {
215 return id1.CompareOrdered(id2) < 0;
216 }
217 };
218
219 /// Check if the handle is a valid or an empty one
220 DECLARE_OPERATOR_BOOL_REF(m_Info);
221
222 /// Reset the handle (remove seq-id reference)
Reset(void)223 void Reset(void)
224 {
225 m_Info.Reset();
226 m_Packed = 0;
227 m_Variant = 0;
228 }
229
230 //
231 bool NCBI_SEQ_EXPORT HaveMatchingHandles(void) const;
232 bool NCBI_SEQ_EXPORT HaveReverseMatch(void) const;
233 bool NCBI_SEQ_EXPORT HaveMatchingHandles(EAllowWeakMatch allow_weak_match) const;
234 bool NCBI_SEQ_EXPORT HaveReverseMatch(EAllowWeakMatch allow_weak_match) const;
235
236 //
237 typedef set<CSeq_id_Handle> TMatches;
238 void NCBI_SEQ_EXPORT GetMatchingHandles(TMatches& matches) const;
239 void NCBI_SEQ_EXPORT GetReverseMatchingHandles(TMatches& matches) const;
240 void NCBI_SEQ_EXPORT GetMatchingHandles(TMatches& matches,
241 EAllowWeakMatch allow_weak_match) const;
242 void NCBI_SEQ_EXPORT GetReverseMatchingHandles(TMatches& matches,
243 EAllowWeakMatch allow_weak_match) const;
244
245 /// True if *this matches to h.
246 /// This mean that *this is either the same as h,
247 /// or more generic version of h.
248 bool NCBI_SEQ_EXPORT MatchesTo(const CSeq_id_Handle& h) const;
249
250 /// True if "this" is a better bioseq than "h".
251 bool NCBI_SEQ_EXPORT IsBetter(const CSeq_id_Handle& h) const;
252
253 string NCBI_SEQ_EXPORT AsString(void) const;
254
Which(void) const255 CSeq_id::E_Choice Which(void) const
256 {
257 return m_Info->GetType();
258 }
IsPacked(void) const259 bool IsPacked(void) const
260 {
261 return m_Packed != 0;
262 }
GetPacked(void) const263 TPacked GetPacked(void) const
264 {
265 return m_Packed;
266 }
IsSetVariant(void) const267 bool IsSetVariant(void) const
268 {
269 return m_Variant != 0;
270 }
GetVariant(void) const271 TVariant GetVariant(void) const
272 {
273 return m_Variant;
274 }
IsGi(void) const275 bool IsGi(void) const
276 {
277 return m_Packed && m_Info->GetType() == CSeq_id::e_Gi;
278 }
GetGi(void) const279 TGi GetGi(void) const
280 {
281 return IsGi()? TGi(m_Packed) : ZERO_GI;
282 }
IsAccVer(void) const283 bool IsAccVer(void) const
284 {
285 if (IsGi()) return false;
286 auto seq_id = GetSeqId();
287 if (!seq_id) return false;
288 auto text_id = seq_id->GetTextseq_Id();
289 return text_id &&
290 text_id->IsSetAccession() &&
291 text_id->IsSetVersion();
292 }
293 unsigned NCBI_SEQ_EXPORT GetHash(void) const;
294
IdentifyAccession(void) const295 CSeq_id::EAccessionInfo IdentifyAccession(void) const
296 {
297 return GetSeqId()->IdentifyAccession();
298 }
299
GetSeqId(void) const300 CConstRef<CSeq_id> GetSeqId(void) const
301 {
302 CConstRef<CSeq_id> ret;
303 if ( m_Packed || m_Variant ) {
304 ret = m_Info->GetPackedSeqId(m_Packed, m_Variant);
305 }
306 else {
307 ret = m_Info->GetSeqId();
308 }
309 return ret;
310 }
GetSeqIdOrNull(void) const311 CConstRef<CSeq_id> GetSeqIdOrNull(void) const
312 {
313 if ( !m_Info ) {
314 return null;
315 }
316 return GetSeqId();
317 }
318
GetMapper(void) const319 CSeq_id_Mapper& GetMapper(void) const
320 {
321 return m_Info->GetMapper();
322 }
323
Swap(CSeq_id_Handle & idh)324 void Swap(CSeq_id_Handle& idh)
325 {
326 m_Info.Swap(idh.m_Info);
327 swap(m_Packed, idh.m_Packed);
328 swap(m_Variant, idh.m_Variant);
329 }
330
331 public:
x_GetInfo(void) const332 const CSeq_id_Info* x_GetInfo(void) const {
333 return m_Info;
334 }
335
336 private:
337 friend class CSeq_id_Mapper;
338 friend class CSeq_id_Which_Tree;
339
340 // Seq-id info
341 CConstRef<CSeq_id_Info, CSeq_id_InfoLocker> m_Info;
342 TPacked m_Packed;
343 TVariant m_Variant;
344 };
345
346 /// Get CConstRef<CSeq_id> from a seq-id handle (for container
347 /// searching template functions)
348 template<>
349 inline
Get_ConstRef_Seq_id(const CSeq_id_Handle & idh)350 CConstRef<CSeq_id> Get_ConstRef_Seq_id(const CSeq_id_Handle& idh)
351 {
352 return idh.GetSeqId();
353 }
354
355
356 /////////////////////////////////////////////////////////////////////
357 //
358 // Inline methods
359 //
360 /////////////////////////////////////////////////////////////////////
361
362 /* @} */
363
364
365 /// Return best label for a sequence from single Seq-id, or set of Seq-ids.
366 /// Return empty string if the label cannot be determined.
367 /// GetDirectLabel() will return non-empty string only if the Seq-id is
368 /// very likely enough to get good label without loading full set of
369 /// sequence Seq-ids.
370 NCBI_SEQ_EXPORT string GetDirectLabel(const CSeq_id& id);
371 NCBI_SEQ_EXPORT string GetDirectLabel(const CSeq_id_Handle& id);
372 NCBI_SEQ_EXPORT string GetLabel(const CSeq_id& id);
373 NCBI_SEQ_EXPORT string GetLabel(const CSeq_id_Handle& id);
374 NCBI_SEQ_EXPORT string GetLabel(const vector<CSeq_id_Handle>& ids);
375 NCBI_SEQ_EXPORT string GetLabel(const vector<CRef<CSeq_id> >& ids);
376
377
378 NCBI_SEQ_EXPORT
379 CNcbiOstream& operator<<(CNcbiOstream& out, const CSeq_id_Handle& idh);
380
381
END_SCOPE(objects)382 END_SCOPE(objects)
383 END_NCBI_SCOPE
384
385 BEGIN_STD_SCOPE
386 inline
387 void swap(NCBI_NS_NCBI::objects::CSeq_id_Handle& idh1,
388 NCBI_NS_NCBI::objects::CSeq_id_Handle& idh2)
389 {
390 idh1.Swap(idh2);
391 }
392
393 END_STD_SCOPE
394
395 #endif /* OBJECTS_OBJMGR___SEQ_ID_HANDLE__HPP */
396