1 /*  $Id: seq_entry_ci.cpp 483569 2015-11-02 17:27:19Z vasilche $
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 *    Handle to Seq-entry object
30 *
31 */
32 
33 #include <ncbi_pch.hpp>
34 #include <objmgr/seq_entry_ci.hpp>
35 
36 #include <objmgr/impl/seq_entry_info.hpp>
37 #include <objmgr/impl/scope_impl.hpp>
38 #include <objmgr/impl/bioseq_set_info.hpp>
39 
40 #include <objects/seqset/Bioseq_set.hpp>
41 
42 
43 BEGIN_NCBI_SCOPE
BEGIN_SCOPE(objects)44 BEGIN_SCOPE(objects)
45 
46 
47 /////////////////////////////////////////////////////////////////////////////
48 // CSeq_entry_CI
49 /////////////////////////////////////////////////////////////////////////////
50 
51 
52 CSeq_entry_CI::CSeq_entry_CI(const CSeq_entry_Handle& entry,
53                              TFlags flags,
54                              CSeq_entry::E_Choice     type_filter )
55     : m_Flags(flags),
56       m_Filter(type_filter)
57 {
58     if ( m_Flags & fIncludeGivenEntry ) {
59         m_Current = entry;
60         while ((*this)  &&  !x_ValidType()) {
61             x_Next();
62         }
63     } else {
64         if ( entry.IsSet() ) {
65             x_Initialize( entry.GetSet() );
66         }
67     }
68 }
69 
70 
CSeq_entry_CI(const CBioseq_set_Handle & seqset,TFlags flags,CSeq_entry::E_Choice type_filter)71 CSeq_entry_CI::CSeq_entry_CI(const CBioseq_set_Handle& seqset,
72                              TFlags flags,
73                              CSeq_entry::E_Choice      type_filter )
74     : m_Flags(flags),
75       m_Filter(type_filter)
76 {
77     x_Initialize(seqset);
78 }
79 
80 
CSeq_entry_CI(const CSeq_entry_CI & iter)81 CSeq_entry_CI::CSeq_entry_CI(const CSeq_entry_CI& iter)
82 {
83     *this = iter;
84 }
85 
86 
operator =(const CSeq_entry_CI & iter)87 CSeq_entry_CI& CSeq_entry_CI::operator =(const CSeq_entry_CI& iter)
88 {
89     if (this != &iter) {
90         m_Parent = iter.m_Parent;
91         m_Index = iter.m_Index;
92         m_Current = iter.m_Current;
93         m_Flags    = iter.m_Flags;
94         m_Filter = iter.m_Filter;
95         if ( iter.m_SubIt.get() ) {
96             m_SubIt.reset(new CSeq_entry_CI(*iter.m_SubIt));
97         }
98     }
99     return *this;
100 }
101 
102 
x_Initialize(const CBioseq_set_Handle & seqset)103 void CSeq_entry_CI::x_Initialize(const CBioseq_set_Handle& seqset)
104 {
105     if ( seqset ) {
106         m_Parent = seqset;
107         m_Index = 0;
108         x_SetCurrentEntry();
109         while ((*this)  &&  !x_ValidType()) {
110             x_Next();
111         }
112     }
113 }
114 
115 
x_SetCurrentEntry(void)116 void CSeq_entry_CI::x_SetCurrentEntry(void)
117 {
118     if ( m_Parent ) {
119         const vector< CRef<CSeq_entry_Info> >& entries =
120             m_Parent.x_GetInfo().GetSeq_set();
121         if ( m_Index < entries.size() ) {
122             m_Current = CSeq_entry_Handle(*entries[m_Index],
123                                           m_Parent.GetTSE_Handle());
124             return;
125         }
126     }
127     m_Current.Reset();
128 }
129 
130 
operator ++(void)131 CSeq_entry_CI& CSeq_entry_CI::operator ++(void)
132 {
133     do {
134         x_Next();
135     }
136     while ((*this)  &&  !x_ValidType());
137     return *this;
138 }
139 
140 
x_ValidType(void) const141 bool CSeq_entry_CI::x_ValidType(void) const
142 {
143     _ASSERT(*this);
144     switch ( m_Filter ) {
145     case CSeq_entry::e_Seq:
146         return (*this)->IsSeq();
147     case CSeq_entry::e_Set:
148         return (*this)->IsSet();
149     default:
150         break;
151     }
152     return true;
153 }
154 
155 
x_Next(void)156 void CSeq_entry_CI::x_Next(void)
157 {
158     if ( !(*this) ) {
159         return;
160     }
161 
162     if ( m_SubIt.get() ) {
163         // There should not even be a m_SubIt unless we're
164         // in recursive mode
165         _ASSERT(m_Flags & fRecursive);
166         // m_SubIt implies m_Parent
167         _ASSERT( m_Parent );
168         // Already inside sub-entry - try to move forward.
169         ++(*m_SubIt);
170         if ( *m_SubIt ) {
171             return;
172         }
173         // End of sub-entry, continue to the next entry.
174         m_SubIt.reset();
175     }
176     else if ( m_Current.IsSet() ) {
177         // don't set up m_SubIt unless parent is already set up
178         if( ! m_Parent ) {
179             x_Initialize(m_Current.GetSet());
180             return;
181         } else if( m_Flags & fRecursive ) {
182             // Current entry is a seq-set and we're in recursive mode,
183             // so iterate sub-entries.
184             m_SubIt.reset(new CSeq_entry_CI(
185                 m_Current,
186                 (m_Flags & ~fIncludeGivenEntry), // some flags don't get passed down recursively
187                 m_Filter ));
188             if ( *m_SubIt ) {
189                 return;
190             }
191             // Empty sub-entry, continue to the next entry.
192             m_SubIt.reset();
193         }
194     }
195 
196     // "if m_Parent" is really just a proxy for seeing if m_Index is valid,
197     // otherwise incrementing is undefined
198     if( m_Parent ) {
199         ++m_Index;
200     }
201     x_SetCurrentEntry();
202 }
203 
204 
GetDepth(void) const205 int CSeq_entry_CI::GetDepth(void) const
206 {
207     // first, calculate depth assuming the "given" entry has
208     // a depth of zero
209     const int iDepthFromGiven =
210         ( m_SubIt.get() ?
211             2 + m_SubIt->GetDepth() :
212             (  m_Parent ? 1 : 0 )
213         );
214 
215     if( (m_Flags & fIncludeGivenEntry) ) {
216         return iDepthFromGiven;
217     } else {
218         // if given entry is not supposed to be included in the iteration,
219         // it's children get a depth of zero, so we subtract by 1.
220         _ASSERT( iDepthFromGiven > 0 );
221         return (iDepthFromGiven - 1);
222     }
223 }
224 
225 
226 /////////////////////////////////////////////////////////////////////////////
227 // CSeq_entry_I
228 /////////////////////////////////////////////////////////////////////////////
229 
230 
CSeq_entry_I(const CSeq_entry_EditHandle & entry,TFlags flags,CSeq_entry::E_Choice type_filter)231 CSeq_entry_I::CSeq_entry_I(const CSeq_entry_EditHandle& entry,
232                            TFlags flags,
233                            CSeq_entry::E_Choice         type_filter)
234     : CSeq_entry_CI(entry, flags, type_filter)
235 {
236 }
237 
238 
CSeq_entry_I(const CBioseq_set_EditHandle & seqset,TFlags flags,CSeq_entry::E_Choice type_filter)239 CSeq_entry_I::CSeq_entry_I(const CBioseq_set_EditHandle& seqset,
240                            TFlags flags,
241                            CSeq_entry::E_Choice          type_filter)
242     : CSeq_entry_CI(seqset, flags, type_filter)
243 {
244 }
245 
246 
CSeq_entry_I(const CSeq_entry_I & iter)247 CSeq_entry_I::CSeq_entry_I(const CSeq_entry_I& iter)
248 {
249     *this = iter;
250 }
251 
252 
operator =(const CSeq_entry_I & iter)253 CSeq_entry_I& CSeq_entry_I::operator =(const CSeq_entry_I& iter)
254 {
255     CSeq_entry_CI::operator=(iter);
256     return *this;
257 }
258 
259 
260 END_SCOPE(objects)
261 END_NCBI_SCOPE
262