]> git.donarmstrong.com Git - bamtools.git/blob - src/api/SamProgramChain.cpp
Minor cleanup
[bamtools.git] / src / api / SamProgramChain.cpp
1 // ***************************************************************************
2 // SamProgramChain.cpp (c) 2011 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 19 April 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides methods for operating on a SamProgram record "chain"
8 // ***************************************************************************
9
10 #include <api/SamProgramChain.h>
11 using namespace BamTools;
12
13 #include <algorithm>
14 #include <iostream>
15 #include <cstdlib>
16 using namespace std;
17
18 /*! \class BamTools::SamProgramChain
19     \brief Sorted container "chain" of SamProgram records.
20
21     Provides methods for operating on a collection of SamProgram records.
22
23     N.B. - Underlying container is *NOT* ordered by linkage, but by order of
24     appearance in SamHeader and subsequent Add() calls. Using the current
25     iterators will not allow you to step through the header's program history.
26     Instead use First()/Last() to access oldest/newest records, respectively.
27 */
28
29 /*! \fn SamProgramChain::SamProgramChain(void)
30     \brief constructor
31 */
32 SamProgramChain::SamProgramChain(void) { }
33
34 /*! \fn SamProgramChain::SamProgramChain(const SamProgramChain& other)
35     \brief copy constructor
36 */
37 SamProgramChain::SamProgramChain(const SamProgramChain& other)
38     : m_data(other.m_data)
39 { }
40
41 /*! \fn SamProgramChain::~SamProgramChain(void)
42     \brief destructor
43 */
44 SamProgramChain::~SamProgramChain(void) { }
45
46 /*! \fn void SamProgramChain::Add(SamProgram& program)
47     \brief Appends a program to program chain.
48
49     Duplicate entries are silently discarded.
50
51     N.B. - Underlying container is *NOT* ordered by linkage, but by order of
52     appearance in SamHeader and subsequent Add() calls. Using the current
53     iterators will not allow you to step through the header's program history.
54     Instead use First()/Last() to access oldest/newest records, respectively.
55
56     \param program entry to be appended
57 */
58 void SamProgramChain::Add(SamProgram& program) {
59
60     // ignore duplicated records
61     if ( Contains(program) )
62         return;
63
64     // if other programs already in chain, try to find the "next" record
65     // tries to match another record's PPID with @program's ID
66     if ( !IsEmpty() )
67         program.NextProgramID = NextIdFor(program.ID);
68
69     // store program record
70     m_data.push_back(program);
71 }
72
73 /*! \fn void SamProgramChain::Add(const std::vector<SamProgram>& programs)
74     \brief Appends a batch of programs to the end of the chain.
75
76     This is an overloaded function.
77
78     \param programs batch of program records to append
79     \sa Add()
80 */
81 void SamProgramChain::Add(std::vector<SamProgram>& programs) {
82     vector<SamProgram>::iterator pgIter = programs.begin();
83     vector<SamProgram>::iterator pgEnd  = programs.end();
84     for ( ; pgIter != pgEnd; ++pgIter )
85         Add(*pgIter);
86 }
87
88 /*! \fn SamProgramIterator SamProgramChain::Begin(void)
89     \return an STL iterator pointing to the first (oldest) program record
90     \sa ConstBegin(), End(), First()
91 */
92 SamProgramIterator SamProgramChain::Begin(void) {
93     return m_data.begin();
94 }
95
96 /*! \fn SamProgramConstIterator SamProgramChain::Begin(void) const
97     \return an STL const_iterator pointing to the first (oldest) program record
98
99     This is an overloaded function.
100
101     \sa ConstBegin(), End(), First()
102 */
103 SamProgramConstIterator SamProgramChain::Begin(void) const {
104     return m_data.begin();
105 }
106
107 /*! \fn void SamProgramChain::Clear(void)
108     \brief Clears all program records.
109 */
110 void SamProgramChain::Clear(void) {
111     m_data.clear();
112 }
113
114 /*! \fn SamProgramConstIterator SamProgramChain::ConstBegin(void) const
115     \return an STL const_iterator pointing to the first (oldest) program record
116     \sa Begin(), ConstEnd(), First()
117 */
118 SamProgramConstIterator SamProgramChain::ConstBegin(void) const {
119     return m_data.begin();
120 }
121
122 /*! \fn SamProgramConstIterator SamProgramChain::ConstEnd(void) const
123     \return an STL const_iterator pointing to the imaginary entry after the last (newest) program record
124     \sa ConstBegin(), End(), Last()
125 */
126 SamProgramConstIterator SamProgramChain::ConstEnd(void) const {
127     return m_data.end();
128 }
129
130 /*! \fn bool SamProgramChain::Contains(const SamProgram& program) const
131     \brief Returns true if chains has this program record (matching on ID).
132
133     This is an overloaded function.
134
135     \param program SamProgram to search for
136     \return \c true if chain contains program (matching on ID)
137 */
138 bool SamProgramChain::Contains(const SamProgram& program) const {
139     return Contains(program.ID);
140 }
141
142 /*! \fn bool SamProgramChain::Contains(const std::string& programId) const
143     \brief Returns true if chains has a program record with this ID
144     \param programId search for program matching this ID
145     \return \c true if chain contains a program record with this ID
146 */
147 bool SamProgramChain::Contains(const std::string& programId) const {
148     return ( IndexOf(programId) != (int)m_data.size() );
149 }
150
151 /*! \fn SamProgramIterator SamProgramChain::End(void)
152     \return an STL iterator pointing to the imaginary entry after the last (newest) program record
153     \sa Begin(), ConstEnd(), Last()
154 */
155 SamProgramIterator SamProgramChain::End(void) {
156     return m_data.end();
157 }
158
159 /*! \fn SamProgramConstIterator SamProgramChain::End(void) const
160     \return an STL const_iterator pointing to the imaginary entry after the last (newest) program record
161
162     This is an overloaded function.
163
164     \sa Begin(), ConstEnd(), Last()
165 */
166 SamProgramConstIterator SamProgramChain::End(void) const {
167     return m_data.end();
168 }
169
170 /*! \fn SamProgram& SamProgramChain::First(void)
171     \brief Fetches first (oldest) record in the chain.
172
173     N.B. - This function will fail if the chain is empty. If this is possible,
174     check the result of IsEmpty() before calling this function.
175
176     \return a modifiable reference to the first (oldest) program entry
177     \sa Begin(), Last()
178 */
179 SamProgram& SamProgramChain::First(void) {
180
181     // find first record in container that has no PreviousProgramID entry
182     SamProgramIterator iter = Begin();
183     SamProgramIterator end  = End();
184     for ( ; iter != end; ++iter ) {
185         SamProgram& current = (*iter);
186         if ( !current.HasPreviousProgramID() )
187             return current;
188     }
189
190     // otherwise error
191     cerr << "SamProgramChain ERROR - could not find any record without a PP tag" << endl;
192     exit(1);
193 }
194
195 /*! \fn const SamProgram& SamProgramChain::First(void) const
196     \brief Fetches first (oldest) record in the chain.
197
198     This is an overloaded function.
199
200     N.B. - This function will fail if the chain is empty. If this is possible,
201     check the result of IsEmpty() before calling this function.
202
203     \return a read-only reference to the first (oldest) program entry
204     \sa Begin(), ConstBegin(), Last()
205 */
206 const SamProgram& SamProgramChain::First(void) const {
207
208     // find first record in container that has no PreviousProgramID entry
209     SamProgramConstIterator iter = ConstBegin();
210     SamProgramConstIterator end  = ConstEnd();
211     for ( ; iter != end; ++iter ) {
212         const SamProgram& current = (*iter);
213         if ( !current.HasPreviousProgramID() )
214             return current;
215     }
216
217     // otherwise error
218     cerr << "SamProgramChain ERROR - could not find any record without a PP tag" << endl;
219     exit(1);
220 }
221
222 /*! \fn int SamProgramChain::IndexOf(const std::string& programId) const
223     \internal
224     \return index of program record if found.
225     Otherwise, returns vector::size() (invalid index).
226 */
227 int SamProgramChain::IndexOf(const std::string& programId) const {
228     SamProgramConstIterator begin = ConstBegin();
229     SamProgramConstIterator iter  = begin;
230     SamProgramConstIterator end   = ConstEnd();
231     for ( ; iter != end; ++iter ) {
232         const SamProgram& current = (*iter);
233         if ( current.ID == programId )
234             break;
235     }
236     return distance( begin, iter );
237 }
238
239 /*! \fn bool SamProgramChain::IsEmpty(void) const
240     \brief Returns \c true if chain contains no records
241     \sa Size()
242 */
243 bool SamProgramChain::IsEmpty(void) const {
244     return m_data.empty();
245 }
246
247 /*! \fn SamProgram& SamProgramChain::Last(void)
248     \brief Fetches last (newest) record in the chain.
249
250     N.B. - This function will fail if the chain is empty. If this is possible,
251     check the result of IsEmpty() before calling this function.
252
253     \return a modifiable reference to the last (newest) program entry
254     \sa End(), First()
255 */
256 SamProgram& SamProgramChain::Last(void) {
257     // find first record in container that has no NextProgramID entry
258     SamProgramIterator iter = Begin();
259     SamProgramIterator end  = End();
260     for ( ; iter != end; ++iter ) {
261         SamProgram& current = (*iter);
262         if ( !current.HasNextProgramID() )
263             return current;
264     }
265
266     // otherwise error
267     cerr << "SamProgramChain ERROR - could not determine last record" << endl;
268     exit(1);
269 }
270
271 /*! \fn const SamProgram& SamProgramChain::Last(void) const
272     \brief Fetches last (newest) record in the chain.
273
274     This is an overloaded function.
275
276     N.B. - This function will fail if the chain is empty. If this is possible,
277     check the result of IsEmpty() before calling this function.
278
279     \return a read-only reference to the last (newest) program entry
280     \sa End(), ConstEnd(), First()
281 */
282 const SamProgram& SamProgramChain::Last(void) const {
283     // find first record in container that has no NextProgramID entry
284     SamProgramConstIterator iter = ConstBegin();
285     SamProgramConstIterator end  = ConstEnd();
286     for ( ; iter != end; ++iter ) {
287         const SamProgram& current = (*iter);
288         if ( !current.HasNextProgramID() )
289             return current;
290     }
291
292     // otherwise error
293     cerr << "SamProgramChain ERROR - could not determine last record" << endl;
294     exit(1);
295 }
296
297 /*! \fn const std::string SamProgramChain::NextIdFor(const std::string& programId) const
298     \internal
299     \return ID of program record, whose PreviousProgramID matches \a programId.
300     Otherwise, returns empty string if none found.
301 */
302 const std::string SamProgramChain::NextIdFor(const std::string& programId) const {
303
304     // find first record in container whose PreviousProgramID matches @programId
305     SamProgramConstIterator iter = ConstBegin();
306     SamProgramConstIterator end  = ConstEnd();
307     for ( ; iter != end; ++iter ) {
308         const SamProgram& current = (*iter);
309         if ( !current.HasPreviousProgramID() &&
310               current.PreviousProgramID == programId
311            )
312         {
313             return current.ID;
314         }
315     }
316
317     // none found
318     return string();
319 }
320
321 /*! \fn int SamProgramChain::Size(void) const
322     \brief Returns number of program records in the chain.
323     \sa IsEmpty()
324 */
325 int SamProgramChain::Size(void) const {
326     return m_data.size();
327 }
328
329 /*! \fn SamProgram& SamProgramChain::operator[](const std::string& programId)
330     \brief Retrieves the modifiable SamProgram record that matches \a programId.
331
332     NOTE - If the chain contains no read group matching this ID, this function will
333     print an error and terminate.
334
335     \param programId ID of program record to retrieve
336     \return a modifiable reference to the SamProgram associated with the ID
337 */
338 SamProgram& SamProgramChain::operator[](const std::string& programId) {
339
340     // look up program record matching this ID
341     int index = IndexOf(programId);
342
343     // if record not found
344     if ( index == (int)m_data.size() ) {
345         cerr << "SamProgramChain ERROR - unknown programId: " << programId << endl;
346         exit(1);
347     }
348
349     // otherwise return program record at index
350     return m_data.at(index);
351 }