1 // ***************************************************************************
2 // SamProgramChain.cpp (c) 2011 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 10 October 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides methods for operating on a SamProgram record "chain"
8 // ***************************************************************************
10 #include "api/SamProgramChain.h"
11 using namespace BamTools;
18 /*! \class BamTools::SamProgramChain
19 \brief Sorted container "chain" of SamProgram records.
21 Provides methods for operating on a collection of SamProgram records.
23 \note 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.
29 /*! \fn SamProgramChain::SamProgramChain(void)
32 SamProgramChain::SamProgramChain(void) { }
34 /*! \fn SamProgramChain::SamProgramChain(const SamProgramChain& other)
35 \brief copy constructor
37 SamProgramChain::SamProgramChain(const SamProgramChain& other)
38 : m_data(other.m_data)
41 /*! \fn SamProgramChain::~SamProgramChain(void)
44 SamProgramChain::~SamProgramChain(void) { }
46 /*! \fn void SamProgramChain::Add(SamProgram& program)
47 \brief Appends a program to program chain.
49 Duplicate entries are silently discarded.
51 \note 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.
56 \param[in] program entry to be appended
58 void SamProgramChain::Add(SamProgram& program) {
60 // ignore duplicated records
61 if ( Contains(program) )
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
67 program.NextProgramID = NextIdFor(program.ID);
69 // store program record
70 m_data.push_back(program);
73 /*! \fn void SamProgramChain::Add(std::vector<SamProgram>& programs)
74 \brief Appends a batch of programs to the end of the chain.
76 This is an overloaded function.
78 \param[in] programs batch of program records to append
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 )
88 /*! \fn SamProgramIterator SamProgramChain::Begin(void)
89 \return an STL iterator pointing to the first (oldest) program record
90 \sa ConstBegin(), End(), First()
92 SamProgramIterator SamProgramChain::Begin(void) {
93 return m_data.begin();
96 /*! \fn SamProgramConstIterator SamProgramChain::Begin(void) const
97 \return an STL const_iterator pointing to the first (oldest) program record
99 This is an overloaded function.
101 \sa ConstBegin(), End(), First()
103 SamProgramConstIterator SamProgramChain::Begin(void) const {
104 return m_data.begin();
107 /*! \fn void SamProgramChain::Clear(void)
108 \brief Clears all program records.
110 void SamProgramChain::Clear(void) {
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()
118 SamProgramConstIterator SamProgramChain::ConstBegin(void) const {
119 return m_data.begin();
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()
126 SamProgramConstIterator SamProgramChain::ConstEnd(void) const {
130 /*! \fn bool SamProgramChain::Contains(const SamProgram& program) const
131 \brief Returns true if chains has this program record (matching on ID).
133 This is an overloaded function.
135 \param[in] program SamProgram to search for
136 \return \c true if chain contains program (matching on ID)
138 bool SamProgramChain::Contains(const SamProgram& program) const {
139 return Contains(program.ID);
142 /*! \fn bool SamProgramChain::Contains(const std::string& programId) const
143 \brief Returns true if chains has a program record with this ID
145 \param[in] programId search for program matching this ID
146 \return \c true if chain contains a program record with this ID
148 bool SamProgramChain::Contains(const std::string& programId) const {
149 return ( IndexOf(programId) != (int)m_data.size() );
152 /*! \fn SamProgramIterator SamProgramChain::End(void)
153 \return an STL iterator pointing to the imaginary entry after the last (newest) program record
154 \sa Begin(), ConstEnd(), Last()
156 SamProgramIterator SamProgramChain::End(void) {
160 /*! \fn SamProgramConstIterator SamProgramChain::End(void) const
161 \return an STL const_iterator pointing to the imaginary entry after the last (newest) program record
163 This is an overloaded function.
165 \sa Begin(), ConstEnd(), Last()
167 SamProgramConstIterator SamProgramChain::End(void) const {
171 /*! \fn SamProgram& SamProgramChain::First(void)
172 \brief Fetches first (oldest) record in the chain.
174 \warning This function will fail if the chain is empty. If this is possible,
175 check the result of IsEmpty() before calling this function.
177 \return a modifiable reference to the first (oldest) program entry
180 SamProgram& SamProgramChain::First(void) {
182 // find first record in container that has no PreviousProgramID entry
183 SamProgramIterator iter = Begin();
184 SamProgramIterator end = End();
185 for ( ; iter != end; ++iter ) {
186 SamProgram& current = (*iter);
187 if ( !current.HasPreviousProgramID() )
192 cerr << "SamProgramChain::First: could not find any record without a PP tag" << endl;
196 /*! \fn const SamProgram& SamProgramChain::First(void) const
197 \brief Fetches first (oldest) record in the chain.
199 This is an overloaded function.
201 \warning This function will fail if the chain is empty. If this is possible,
202 check the result of IsEmpty() before calling this function.
204 \return a read-only reference to the first (oldest) program entry
205 \sa Begin(), ConstBegin(), Last()
207 const SamProgram& SamProgramChain::First(void) const {
209 // find first record in container that has no PreviousProgramID entry
210 SamProgramConstIterator iter = ConstBegin();
211 SamProgramConstIterator end = ConstEnd();
212 for ( ; iter != end; ++iter ) {
213 const SamProgram& current = (*iter);
214 if ( !current.HasPreviousProgramID() )
219 cerr << "SamProgramChain::First: could not find any record without a PP tag" << endl;
223 /*! \fn int SamProgramChain::IndexOf(const std::string& programId) const
225 \return index of program record if found.
226 Otherwise, returns vector::size() (invalid index).
228 int SamProgramChain::IndexOf(const std::string& programId) const {
229 SamProgramConstIterator begin = ConstBegin();
230 SamProgramConstIterator iter = begin;
231 SamProgramConstIterator end = ConstEnd();
232 for ( ; iter != end; ++iter ) {
233 const SamProgram& current = (*iter);
234 if ( current.ID == programId )
237 return distance( begin, iter );
240 /*! \fn bool SamProgramChain::IsEmpty(void) const
241 \brief Returns \c true if chain contains no records
244 bool SamProgramChain::IsEmpty(void) const {
245 return m_data.empty();
248 /*! \fn SamProgram& SamProgramChain::Last(void)
249 \brief Fetches last (newest) record in the chain.
251 \warning This function will fail if the chain is empty. If this is possible,
252 check the result of IsEmpty() before calling this function.
254 \return a modifiable reference to the last (newest) program entry
257 SamProgram& SamProgramChain::Last(void) {
258 // find first record in container that has no NextProgramID entry
259 SamProgramIterator iter = Begin();
260 SamProgramIterator end = End();
261 for ( ; iter != end; ++iter ) {
262 SamProgram& current = (*iter);
263 if ( !current.HasNextProgramID() )
268 cerr << "SamProgramChain::Last: could not determine last record" << endl;
272 /*! \fn const SamProgram& SamProgramChain::Last(void) const
273 \brief Fetches last (newest) record in the chain.
275 This is an overloaded function.
277 \warning This function will fail if the chain is empty. If this is possible,
278 check the result of IsEmpty() before calling this function.
280 \return a read-only reference to the last (newest) program entry
281 \sa End(), ConstEnd(), First()
283 const SamProgram& SamProgramChain::Last(void) const {
284 // find first record in container that has no NextProgramID entry
285 SamProgramConstIterator iter = ConstBegin();
286 SamProgramConstIterator end = ConstEnd();
287 for ( ; iter != end; ++iter ) {
288 const SamProgram& current = (*iter);
289 if ( !current.HasNextProgramID() )
294 cerr << "SamProgramChain::Last: could not determine last record" << endl;
298 /*! \fn const std::string SamProgramChain::NextIdFor(const std::string& programId) const
301 \return ID of program record, whose PreviousProgramID matches \a programId.
302 Otherwise, returns empty string if none found.
304 const std::string SamProgramChain::NextIdFor(const std::string& programId) const {
306 // find first record in container whose PreviousProgramID matches @programId
307 SamProgramConstIterator iter = ConstBegin();
308 SamProgramConstIterator end = ConstEnd();
309 for ( ; iter != end; ++iter ) {
310 const SamProgram& current = (*iter);
311 if ( !current.HasPreviousProgramID() &&
312 current.PreviousProgramID == programId
323 /*! \fn int SamProgramChain::Size(void) const
324 \brief Returns number of program records in the chain.
327 int SamProgramChain::Size(void) const {
328 return m_data.size();
331 /*! \fn SamProgram& SamProgramChain::operator[](const std::string& programId)
332 \brief Retrieves the modifiable SamProgram record that matches \a programId.
334 \warning If the chain contains no read group matching this ID, this function will
335 print an error and terminate. Check the return value of Contains() if this may be
338 \param[in] programId ID of program record to retrieve
339 \return a modifiable reference to the SamProgram associated with the ID
341 SamProgram& SamProgramChain::operator[](const std::string& programId) {
343 // look up program record matching this ID
344 int index = IndexOf(programId);
346 // if record not found
347 if ( index == (int)m_data.size() ) {
348 cerr << "SamProgramChain::operator[] - unknown programId: " << programId << endl;
352 // otherwise return program record at index
353 return m_data.at(index);