00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "SamFileHeader.h"
00019 #include "SamHeaderSQ.h"
00020 #include "SamHeaderRG.h"
00021
00022
00023 const std::string SamFileHeader::EMPTY_RETURN = "";
00024
00025 SamFileHeader::SamFileHeader()
00026 : myHD(NULL),
00027 myReferenceInfo(),
00028 myErrorMessage("")
00029 {
00030 resetHeader();
00031
00032 mySQs.setCaseSensitive(true);
00033 myRGs.setCaseSensitive(true);
00034 myPGs.setCaseSensitive(true);
00035 }
00036
00037
00038 SamFileHeader::~SamFileHeader()
00039 {
00040 resetHeader();
00041 }
00042
00043
00044
00045 SamFileHeader::SamFileHeader(const SamFileHeader& header)
00046 {
00047 copy(header);
00048 }
00049
00050
00051
00052 SamFileHeader & SamFileHeader::operator = (const SamFileHeader& header)
00053 {
00054 copy(header);
00055 return(*this);
00056 }
00057
00058
00059 bool SamFileHeader::copy(const SamFileHeader& header)
00060 {
00061
00062 if(this == &header)
00063 {
00064 return(true);
00065 }
00066
00067 resetHeader();
00068
00069
00070
00071 std::string newString;
00072 bool status = header.getHeaderString(newString);
00073 String newHeaderString = newString.c_str();
00074
00075 status &= parseHeader(newHeaderString);
00076
00077 myCurrentHeaderIndex = header.myCurrentHeaderIndex;
00078 myCurrentCommentIndex = header.myCurrentCommentIndex;
00079
00080
00081 myReferenceInfo.clear();
00082
00083 myReferenceInfo = header.myReferenceInfo;
00084
00085 return(status);
00086 }
00087
00088
00089
00090 void SamFileHeader::resetHeader()
00091 {
00092 myReferenceInfo.clear();
00093
00094
00095
00096 myHD = NULL;
00097 mySQs.Clear();
00098 myRGs.Clear();
00099 myPGs.Clear();
00100
00101
00102 for(unsigned int headerIndex = 0; headerIndex < myHeaderRecords.size();
00103 headerIndex++)
00104 {
00105 if(myHeaderRecords[headerIndex] != NULL)
00106 {
00107 delete myHeaderRecords[headerIndex];
00108 myHeaderRecords[headerIndex] = NULL;
00109 }
00110 }
00111 myHeaderRecords.clear();
00112
00113
00114 resetHeaderRecordIter();
00115
00116
00117 resetCommentIter();
00118
00119
00120 resetSQRecordIter();
00121 resetRGRecordIter();
00122 resetPGRecordIter();
00123
00124
00125 myComments.clear();
00126 }
00127
00128
00129
00130
00131 bool SamFileHeader::getHeaderString(std::string& header) const
00132 {
00133 header.clear();
00134
00135
00136 unsigned int index = 0;
00137 while(getHeaderLine(index, header) != false)
00138 {
00139 ++index;
00140 }
00141
00142 return(true);
00143 }
00144
00145
00146 int SamFileHeader::getReferenceID(const String & referenceName, bool addID)
00147 {
00148 return(myReferenceInfo.getReferenceID(referenceName, addID));
00149 }
00150
00151
00152 int SamFileHeader::getReferenceID(const char* referenceName, bool addID)
00153 {
00154 return(myReferenceInfo.getReferenceID(referenceName, addID));
00155 }
00156
00157
00158 const String & SamFileHeader::getReferenceLabel(int id) const
00159 {
00160 return(myReferenceInfo.getReferenceLabel(id));
00161 }
00162
00163
00164
00165 const SamReferenceInfo& SamFileHeader::getReferenceInfo() const
00166 {
00167 return(myReferenceInfo);
00168 }
00169
00170
00171
00172
00173 SamReferenceInfo& SamFileHeader::getReferenceInfoForBamInterface()
00174 {
00175 return(myReferenceInfo);
00176 }
00177
00178
00179
00180 bool SamFileHeader::addHeaderLine(const char* type, const char* tag,
00181 const char* value)
00182 {
00183 String headerLine;
00184 headerLine += "@";
00185 headerLine += type;
00186 headerLine += "\t";
00187 headerLine += tag;
00188 headerLine += ":";
00189 headerLine += value;
00190 return(addHeaderLine(headerLine.c_str()));
00191 }
00192
00193
00194
00195 bool SamFileHeader::addHeaderLine(const char* headerLine)
00196 {
00197
00198 String headerString = headerLine;
00199 return(parseHeader(headerString));
00200 }
00201
00202
00203
00204 bool SamFileHeader::addHeader(const char* header)
00205 {
00206
00207 String headerString = header;
00208 return(parseHeader(headerString));
00209 }
00210
00211
00212
00213 bool SamFileHeader::addComment(const char* comment)
00214 {
00215 if((comment != NULL) && (strcmp(comment, EMPTY_RETURN.c_str()) != 0))
00216 {
00217
00218 myComments.push_back(comment);
00219 }
00220 return(true);
00221 }
00222
00223
00224
00225 bool SamFileHeader::setHDTag(const char* tag, const char* value)
00226 {
00227 if(myHD == NULL)
00228 {
00229
00230 myHD = new SamHeaderHD();
00231 if(myHD == NULL)
00232 {
00233
00234 myErrorMessage = "SamFileHeader: Failed to allocate a new HD tag";
00235 return(false);
00236 }
00237
00238
00239 myHeaderRecords.push_back(myHD);
00240 }
00241 if(!myHD->setTag(tag, value))
00242 {
00243 myErrorMessage = "SamFileHeader: Failed to set the specified HD tag";
00244 return(false);
00245 }
00246 return(true);
00247 }
00248
00249
00250
00251
00252 bool SamFileHeader::setSQTag(const char* tag, const char* value,
00253 const char* name)
00254 {
00255
00256 SamHeaderSQ* sq = getSQ(name);
00257 if(sq == NULL)
00258 {
00259
00260
00261 if(strcmp(tag, "LN") != 0)
00262 {
00263
00264 myErrorMessage =
00265 "SamFileHeader:Failed to add the specified SQ key, LN not specified.";
00266 return(false);
00267 }
00268
00269
00270 sq = new SamHeaderSQ();
00271
00272 if(sq == NULL)
00273 {
00274
00275 myErrorMessage = "SamFileHeader: Failed to allocate a new SQ tag";
00276 return(false);
00277 }
00278
00279
00280 mySQs.Add(name, sq);
00281 myHeaderRecords.push_back(sq);
00282
00283 myReferenceInfo.add(name, atoi(value));
00284
00285
00286 if(!sq->addKey(name))
00287 {
00288
00289 myErrorMessage = "SamFileHeader:Failed to add the specified SQ key";
00290 return(false);
00291 }
00292 }
00293 else if(strcmp(tag, "LN") == 0)
00294 {
00295
00296 myErrorMessage = "SamFileHeader:Cannot modify/remove the SQ's LN tag";
00297 return(false);
00298 }
00299
00300 if(!sq->setTag(tag, value))
00301 {
00302 myErrorMessage = "Failed to set the specified SQ tag";
00303 return(false);
00304 }
00305 return(true);
00306 }
00307
00308
00309
00310
00311 bool SamFileHeader::setRGTag(const char* tag, const char* value, const char* id)
00312 {
00313
00314 SamHeaderRG* rg = getRG(id);
00315 if(rg == NULL)
00316 {
00317
00318
00319 rg = new SamHeaderRG();
00320
00321 if(rg == NULL)
00322 {
00323
00324 myErrorMessage = "Failed to allocate a new RG tag";
00325 return(false);
00326 }
00327
00328
00329 myRGs.Add(id, rg);
00330 myHeaderRecords.push_back(rg);
00331
00332
00333 if(!rg->addKey(id))
00334 {
00335
00336 myErrorMessage = "Failed to add the specified RG key";
00337 return(false);
00338 }
00339 }
00340
00341 if(!rg->setTag(tag, value))
00342 {
00343 myErrorMessage = "Failed to set the specified RG tag";
00344 return(false);
00345 }
00346 return(true);
00347 }
00348
00349
00350
00351
00352
00353 bool SamFileHeader::setPGTag(const char* tag, const char* value, const char* id)
00354 {
00355
00356 SamHeaderPG* pg = getPG(id);
00357 if(pg == NULL)
00358 {
00359
00360
00361 pg = new SamHeaderPG();
00362
00363 if(pg == NULL)
00364 {
00365
00366 myErrorMessage = "Failed to allocate a new PG tag";
00367 return(false);
00368 }
00369
00370
00371 myPGs.Add(id, pg);
00372 myHeaderRecords.push_back(pg);
00373
00374
00375 if(!pg->addKey(id))
00376 {
00377
00378 myErrorMessage = "Failed to add the specified PG key";
00379 return(false);
00380 }
00381 }
00382
00383 if(!pg->setTag(tag, value))
00384 {
00385 myErrorMessage = "Failed to set the specified PG tag";
00386 return(false);
00387 }
00388 return(true);
00389 }
00390
00391
00392
00393 bool SamFileHeader::addHD(SamHeaderHD* hd)
00394 {
00395
00396
00397 if(myHD != NULL)
00398 {
00399 myErrorMessage = "Failed add an HD tag - there is already one";
00400 return(false);
00401 }
00402 if(hd == NULL)
00403 {
00404 myErrorMessage = "Failed add an HD tag - no tag specified";
00405 return(false);
00406 }
00407 myHD = hd;
00408
00409 myHeaderRecords.push_back(myHD);
00410 return(true);
00411 }
00412
00413
00414
00415 bool SamFileHeader::addSQ(SamHeaderSQ* sq)
00416 {
00417 if(sq == NULL)
00418 {
00419
00420 myErrorMessage = "SAM/BAM Header line failed to allocate SQ.";
00421 return(false);
00422 }
00423 const char* name = sq->getTagValue("SN");
00424 const char* length = sq->getTagValue("LN");
00425 if(strcmp(name, EMPTY_RETURN.c_str()) == 0)
00426 {
00427
00428 myErrorMessage =
00429 "SAM/BAM Header line failure: Skipping SQ line that is missing the SN field.";
00430 return(false);
00431 }
00432 if(strcmp(length, EMPTY_RETURN.c_str()) == 0)
00433 {
00434
00435 myErrorMessage =
00436 "SAM/BAM Header line failure: Skipping SQ line that is missing the LN field.";
00437 return(false);
00438 }
00439
00440
00441
00442 if(mySQs.Find(name) < 0)
00443 {
00444
00445 mySQs.Add(name, sq);
00446 myHeaderRecords.push_back(sq);
00447 myReferenceInfo.add(name, atoi(length));
00448 return(true);
00449 }
00450
00451
00452 myErrorMessage = "SAM/BAM Header line failure: Skipping SQ line that has a repeated SN field.";
00453 return(false);
00454 }
00455
00456
00457
00458 bool SamFileHeader::addRG(SamHeaderRG* rg)
00459 {
00460 if(rg == NULL)
00461 {
00462
00463 myErrorMessage = "SAM/BAM Header line failed to allocate RG.";
00464 return(false);
00465 }
00466 const char* id = rg->getTagValue("ID");
00467 if(strcmp(id, EMPTY_RETURN.c_str()) == 0)
00468 {
00469
00470 myErrorMessage = "SAM/BAM Header line failure: Skipping RG line that is missing the ID field.";
00471 return(false);
00472 }
00473
00474
00475
00476 if(myRGs.Find(id) < 0)
00477 {
00478
00479
00480 myRGs.Add(id, rg);
00481 myHeaderRecords.push_back(rg);
00482 return(true);
00483 }
00484
00485
00486 myErrorMessage = "SAM/BAM Header line failure: Skipping RG line that has a repeated ID field.";
00487 return(false);
00488 }
00489
00490
00491
00492 bool SamFileHeader::addPG(SamHeaderPG* pg)
00493 {
00494
00495 if(pg == NULL)
00496 {
00497 myErrorMessage = "SAM/BAM Header line failed to allocate PG.";
00498 return(false);
00499 }
00500 const char* id = pg->getTagValue("ID");
00501 if(strcmp(id, EMPTY_RETURN.c_str()) == 0)
00502 {
00503
00504 myErrorMessage = "SAM/BAM Header line failure: Skipping PG line that is missing the ID field.";
00505 return(false);
00506 }
00507
00508
00509
00510 if(myPGs.Find(id) < 0)
00511 {
00512
00513
00514 myPGs.Add(id, pg);
00515 myHeaderRecords.push_back(pg);
00516 return(true);
00517 }
00518
00519
00520 myErrorMessage = "SAM/BAM Header line failure: Skipping PG line that has a repeated ID field.";
00521 return(false);
00522 }
00523
00524
00525
00526 bool SamFileHeader::addRecordCopy(const SamHeaderRecord& hdrRec)
00527 {
00528 SamHeaderRecord* newRec = hdrRec.createCopy();
00529 bool returnVal = true;
00530 switch(newRec->getType())
00531 {
00532 case SamHeaderRecord::HD:
00533 returnVal = addHD((SamHeaderHD*)newRec);
00534 break;
00535 case SamHeaderRecord::PG:
00536 returnVal = addPG((SamHeaderPG*)newRec);
00537 break;
00538 case SamHeaderRecord::RG:
00539 returnVal = addRG((SamHeaderRG*)newRec);
00540 break;
00541 case SamHeaderRecord::SQ:
00542 returnVal = addSQ((SamHeaderSQ*)newRec);
00543 break;
00544 default:
00545 myErrorMessage = "Failed to copy a header record, unknown type.";
00546 returnVal = false;
00547 break;
00548 }
00549 return(returnVal);
00550 }
00551
00552
00553
00554 bool SamFileHeader::removeHD()
00555 {
00556 if(myHD != NULL)
00557 {
00558
00559
00560
00561
00562 myHD->reset();
00563
00564
00565 myHD = NULL;
00566 }
00567
00568 return(true);
00569 }
00570
00571
00572
00573 bool SamFileHeader::removeSQ(const char* name)
00574 {
00575
00576 int hashIndex = mySQs.Find(name);
00577 if(hashIndex < 0)
00578 {
00579
00580
00581
00582 return(true);
00583 }
00584
00585
00586 SamHeaderSQ* sq = (SamHeaderSQ*)(mySQs.Object(hashIndex));
00587
00588 if(sq == NULL)
00589 {
00590
00591
00592 myErrorMessage = "SAM/BAM Header line failed to get SQ object.";
00593 return(false);
00594 }
00595
00596
00597
00598
00599
00600 sq->reset();
00601
00602
00603 mySQs.Delete(hashIndex);
00604
00605 return(true);
00606 }
00607
00608
00609
00610 bool SamFileHeader::removeRG(const char* id)
00611 {
00612
00613 int hashIndex = myRGs.Find(id);
00614 if(hashIndex < 0)
00615 {
00616
00617
00618
00619 return(true);
00620 }
00621
00622
00623 SamHeaderRG* rg = (SamHeaderRG*)(myRGs.Object(hashIndex));
00624
00625 if(rg == NULL)
00626 {
00627
00628
00629 myErrorMessage = "SAM/BAM Header line failed to get RG object.";
00630 return(false);
00631 }
00632
00633
00634
00635
00636
00637 rg->reset();
00638
00639
00640 myRGs.Delete(hashIndex);
00641
00642 return(true);
00643 }
00644
00645
00646
00647 bool SamFileHeader::removePG(const char* id)
00648 {
00649
00650 int hashIndex = myPGs.Find(id);
00651 if(hashIndex < 0)
00652 {
00653
00654
00655
00656 return(true);
00657 }
00658
00659
00660 SamHeaderPG* pg = (SamHeaderPG*)(myPGs.Object(hashIndex));
00661
00662 if(pg == NULL)
00663 {
00664
00665
00666 myErrorMessage = "SAM/BAM Header line failed to get PG object.";
00667 return(false);
00668 }
00669
00670
00671
00672
00673
00674 pg->reset();
00675
00676
00677 myPGs.Delete(hashIndex);
00678
00679 return(true);
00680 }
00681
00682
00683 const char* SamFileHeader::getHDTagValue(const char* tag)
00684 {
00685 if(myHD == NULL)
00686 {
00687
00688 return(EMPTY_RETURN.c_str());
00689 }
00690 return(myHD->getTagValue(tag));
00691 }
00692
00693
00694
00695
00696 const char* SamFileHeader::getSQTagValue(const char* tag, const char* name)
00697 {
00698
00699 SamHeaderSQ* sq = (SamHeaderSQ*)(mySQs.Object(name));
00700
00701
00702 if(sq == NULL)
00703 {
00704 return(EMPTY_RETURN.c_str());
00705 }
00706
00707
00708 return(sq->getTagValue(tag));
00709 }
00710
00711
00712
00713
00714 const char* SamFileHeader::getRGTagValue(const char* tag, const char* id)
00715 {
00716
00717 SamHeaderRG* rg = (SamHeaderRG*)(myRGs.Object(id));
00718
00719
00720 if(rg == NULL)
00721 {
00722 return(EMPTY_RETURN.c_str());
00723 }
00724
00725
00726 return(rg->getTagValue(tag));
00727 }
00728
00729
00730 const char* SamFileHeader::getPGTagValue(const char* tag, const char* id)
00731 {
00732
00733 SamHeaderPG* pg = (SamHeaderPG*)(myPGs.Object(id));
00734
00735
00736 if(pg == NULL)
00737 {
00738 return(EMPTY_RETURN.c_str());
00739 }
00740
00741
00742 return(pg->getTagValue(tag));
00743 }
00744
00745
00746
00747 int SamFileHeader::getNumSQs()
00748 {
00749 return(mySQs.Entries());
00750 }
00751
00752
00753
00754 int SamFileHeader::getNumRGs()
00755 {
00756 return(myRGs.Entries());
00757 }
00758
00759
00760
00761 int SamFileHeader::getNumPGs()
00762 {
00763 return(myPGs.Entries());
00764 }
00765
00766
00767
00768 SamHeaderHD* SamFileHeader::getHD()
00769 {
00770 return(myHD);
00771 }
00772
00773
00774
00775 SamHeaderSQ* SamFileHeader::getSQ(const char* name)
00776 {
00777 return((SamHeaderSQ*)(mySQs.Object(name)));
00778 }
00779
00780
00781
00782 SamHeaderRG* SamFileHeader::getRG(const char* id)
00783 {
00784 return((SamHeaderRG*)(myRGs.Object(id)));
00785 }
00786
00787
00788
00789 SamHeaderPG* SamFileHeader::getPG(const char* id)
00790 {
00791 return((SamHeaderPG*)(myPGs.Object(id)));
00792 }
00793
00794
00795
00796
00797 const char* SamFileHeader::getSortOrder()
00798 {
00799 if(myHD == NULL)
00800 {
00801
00802 return(EMPTY_RETURN.c_str());
00803 }
00804 return(myHD->getSortOrder());
00805 }
00806
00807
00808
00809 const char* SamFileHeader::getTagSO()
00810 {
00811 return(getSortOrder());
00812 }
00813
00814
00815
00816
00817 SamHeaderRecord* SamFileHeader::getNextSQRecord()
00818 {
00819 return(getNextHeaderRecord(myCurrentSQIndex,
00820 SamHeaderRecord::SQ));
00821 }
00822
00823
00824
00825
00826 SamHeaderRecord* SamFileHeader::getNextRGRecord()
00827 {
00828 return(getNextHeaderRecord(myCurrentRGIndex,
00829 SamHeaderRecord::RG));
00830 }
00831
00832
00833
00834
00835 SamHeaderRecord* SamFileHeader::getNextPGRecord()
00836 {
00837 return(getNextHeaderRecord(myCurrentPGIndex,
00838 SamHeaderRecord::PG));
00839 }
00840
00841
00842
00843
00844 void SamFileHeader::resetSQRecordIter()
00845 {
00846 myCurrentSQIndex = 0;
00847 }
00848
00849
00850
00851
00852 void SamFileHeader::resetRGRecordIter()
00853 {
00854 myCurrentRGIndex = 0;
00855 }
00856
00857
00858
00859
00860 void SamFileHeader::resetPGRecordIter()
00861 {
00862 myCurrentPGIndex = 0;
00863 }
00864
00865
00866
00867
00868
00869
00870
00871 SamHeaderRecord* SamFileHeader::getNextHeaderRecord(uint32_t& index,
00872 SamHeaderRecord::SamHeaderRecordType headerType)
00873 {
00874 SamHeaderRecord* foundRecord = NULL;
00875
00876
00877 while((index < myHeaderRecords.size())
00878 && (foundRecord == NULL))
00879 {
00880
00881 foundRecord = myHeaderRecords[index];
00882
00883 ++index;
00884
00885 if(!foundRecord->isActiveHeaderRecord())
00886 {
00887
00888 foundRecord = NULL;
00889 }
00890
00891 else if(foundRecord->getType() != headerType)
00892 {
00893
00894 foundRecord = NULL;
00895 }
00896 }
00897
00898
00899 return(foundRecord);
00900 }
00901
00902
00903
00904
00905
00906
00907
00908 SamHeaderRecord* SamFileHeader::getNextHeaderRecord()
00909 {
00910
00911 SamHeaderRecord* foundRecord = NULL;
00912
00913
00914 while((myCurrentHeaderIndex < myHeaderRecords.size())
00915 && (foundRecord == NULL))
00916 {
00917
00918 foundRecord = myHeaderRecords[myCurrentHeaderIndex];
00919
00920 ++myCurrentHeaderIndex;
00921
00922 if(!foundRecord->isActiveHeaderRecord())
00923 {
00924
00925 foundRecord = NULL;
00926 }
00927 }
00928
00929
00930 return(foundRecord);
00931 }
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 bool SamFileHeader::getNextHeaderLine(std::string &headerLine)
00942 {
00943 headerLine = EMPTY_RETURN.c_str();
00944
00945
00946
00947 while(headerLine == EMPTY_RETURN.c_str())
00948 {
00949 if(getHeaderLine(myCurrentHeaderIndex, headerLine) == false)
00950 {
00951
00952 return(false);
00953 }
00954 else
00955 {
00956
00957 ++myCurrentHeaderIndex;
00958 }
00959 }
00960 return(true);
00961 }
00962
00963
00964
00965
00966 void SamFileHeader::resetHeaderRecordIter()
00967 {
00968 myCurrentHeaderIndex = 0;
00969 }
00970
00971
00972 void SamFileHeader::appendCommentLines(std::string &commentLines)
00973 {
00974 for(unsigned int i = 0; i < myComments.size(); i++)
00975 {
00976 commentLines += "@CO\t";;
00977 commentLines += myComments[i];
00978 commentLines += "\n";
00979 }
00980 }
00981
00982
00983
00984
00985 const char* SamFileHeader::getNextComment()
00986 {
00987 if(myCurrentCommentIndex < myComments.size())
00988 {
00989 return(myComments[myCurrentCommentIndex++].c_str());
00990 }
00991
00992 return(EMPTY_RETURN.c_str());
00993 }
00994
00995
00996
00997
00998 void SamFileHeader::resetCommentIter()
00999 {
01000 myCurrentCommentIndex = 0;
01001 }
01002
01003
01004
01005 bool SamFileHeader::parseHeader(String& header)
01006 {
01007 std::string errorMessage = "";
01008 int numErrors = 0;
01009 int numValid = 0;
01010
01011
01012 std::vector<String>* types = header.Split('\n');
01013
01014
01015 for(uint32_t index = 0; index < types->size(); index++)
01016 {
01017
01018 if(!parseHeaderLine(types->at(index)))
01019 {
01020 errorMessage += myErrorMessage;
01021 errorMessage += "\n";
01022 ++numErrors;
01023 }
01024 else
01025 {
01026
01027 ++numValid;
01028 }
01029 }
01030
01031
01032 delete types;
01033 types = NULL;
01034
01035 myErrorMessage = errorMessage;
01036 if((numErrors > 0) && (numValid == 0))
01037 {
01038
01039 std::cerr << numErrors
01040 << " invalid SAM/BAM Header lines were skipped due to:\n"
01041 << errorMessage << std::endl;
01042 return(false);
01043 }
01044 else if(numErrors > 0)
01045 {
01046
01047
01048 std::cerr << numErrors
01049 << " invalid SAM/BAM Header lines were skipped due to:\n"
01050 << errorMessage << std::endl;
01051 }
01052
01053 return(true);
01054 }
01055
01056
01057
01058 bool SamFileHeader::parseHeaderLine(const String& headerLine)
01059 {
01060 StringArray tokens;
01061
01062
01063 tokens.ReplaceColumns(headerLine, '\t');
01064
01065 if(tokens.Length() < 1)
01066 {
01067
01068 return(true);
01069 }
01070
01071
01072 if((tokens[0].Length() != 3) || (tokens[0][0] != '@'))
01073 {
01074
01075
01076 myErrorMessage = "SAM/BAM Header line does not start with @ & at least 2 chars.";
01077 return(false);
01078 }
01079
01080 bool status = true;
01081 if(tokens[0] == "@HD")
01082 {
01083 if(myHD == NULL)
01084 {
01085
01086 myHD = new SamHeaderHD();
01087 if(myHD == NULL)
01088 {
01089
01090 myErrorMessage = "SAM/BAM Header line failed to allocate HD.";
01091 return(false);
01092 }
01093 myHeaderRecords.push_back(myHD);
01094 if(!myHD->setFields(tokens))
01095 {
01096 myErrorMessage = "SAM/BAM Header line failed to store HD record.";
01097 status = false;
01098 }
01099 }
01100 else
01101 {
01102
01103 myErrorMessage = "SAM/BAM Header line failure: multiple HD records.";
01104 status = false;
01105 }
01106 }
01107 else if(tokens[0] == "@SQ")
01108 {
01109
01110 SamHeaderSQ* sq = new SamHeaderSQ();
01111
01112 if(sq->setFields(tokens))
01113 {
01114
01115
01116
01117 status &= addSQ(sq);
01118 }
01119 else
01120 {
01121 myErrorMessage = "SAM/BAM Header line failed to store SQ record.";
01122 status = false;
01123 }
01124 }
01125 else if(tokens[0] == "@RG")
01126 {
01127
01128 SamHeaderRG* rg = new SamHeaderRG();
01129
01130 if(rg->setFields(tokens))
01131 {
01132
01133
01134
01135 status &= addRG(rg);
01136 }
01137 else
01138 {
01139 myErrorMessage = "SAM/BAM Header line failed to store RG record.";
01140 status = false;
01141 }
01142 }
01143 else if(tokens[0] == "@PG")
01144 {
01145
01146 SamHeaderPG* pg = new SamHeaderPG();
01147
01148 if(pg->setFields(tokens))
01149 {
01150
01151
01152
01153 status &= addPG(pg);
01154 }
01155 else
01156 {
01157 myErrorMessage = "SAM/BAM Header line failed to store PG record.";
01158 status = false;
01159 }
01160 }
01161 else if(tokens[0] == "@CO")
01162 {
01163 addComment(tokens[1]);
01164 }
01165 else
01166 {
01167
01168 myErrorMessage =
01169 "SAM/BAM Header line failure: Skipping unknown header type, ";
01170 myErrorMessage += (const char*)(tokens[0]);
01171 status = false;
01172 }
01173 return(status);
01174 }
01175
01176
01177
01178
01179
01180
01181 bool SamFileHeader::getHeaderLine(unsigned int index, std::string& header) const
01182 {
01183
01184 if(index < myHeaderRecords.size())
01185 {
01186
01187
01188 SamHeaderRecord* hdrRec = myHeaderRecords[index];
01189 hdrRec->appendString(header);
01190 return(true);
01191 }
01192 else
01193 {
01194 unsigned int commentIndex = index - myHeaderRecords.size();
01195
01196 if(commentIndex < myComments.size())
01197 {
01198
01199 header += "@CO\t";
01200
01201 header += myComments[commentIndex];
01202
01203 header += "\n";
01204 return(true);
01205 }
01206 }
01207
01208 return(false);
01209 }