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