diff --git a/src/main/java/htsjdk/samtools/AbstractSAMHeaderRecord.java b/src/main/java/htsjdk/samtools/AbstractSAMHeaderRecord.java index 769a7a735..7078bf1dc 100644 --- a/src/main/java/htsjdk/samtools/AbstractSAMHeaderRecord.java +++ b/src/main/java/htsjdk/samtools/AbstractSAMHeaderRecord.java @@ -23,13 +23,12 @@ */ package htsjdk.samtools; +import javax.xml.bind.annotation.XmlTransient; import java.io.Serializable; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; -import javax.xml.bind.annotation.XmlTransient; - /** * Base class for the various concrete records in a SAM header, providing uniform * access to the attributes. @@ -113,4 +112,10 @@ protected int attributesHashCode() { @Override public String toString() { return getClass().getSimpleName() + this.mAttributes.toString(); } + + /** + * Returns the record in the SAM line-based text format. Fields are + * separated by '\t' characters. The String is NOT terminated by '\n'. + */ + abstract public String getSAMString(); } diff --git a/src/main/java/htsjdk/samtools/SAMFileHeader.java b/src/main/java/htsjdk/samtools/SAMFileHeader.java index 41eed4a4c..b94598185 100644 --- a/src/main/java/htsjdk/samtools/SAMFileHeader.java +++ b/src/main/java/htsjdk/samtools/SAMFileHeader.java @@ -358,9 +358,14 @@ public int hashCode() { public final SAMFileHeader clone() { final SAMTextHeaderCodec codec = new SAMTextHeaderCodec(); codec.setValidationStringency(ValidationStringency.SILENT); + return codec.decode(new StringLineReader(getSAMString()), "SAMFileHeader.clone"); + } + + @Override + public String getSAMString() { final StringWriter stringWriter = new StringWriter(); - codec.encode(stringWriter, this); - return codec.decode(new StringLineReader(stringWriter.toString()), "SAMFileHeader.clone"); + new SAMTextHeaderCodec().encode(stringWriter, this); + return stringWriter.toString(); } /** Little class to generate program group IDs */ diff --git a/src/main/java/htsjdk/samtools/SAMProgramRecord.java b/src/main/java/htsjdk/samtools/SAMProgramRecord.java index 91d0dac44..f5ddd964a 100644 --- a/src/main/java/htsjdk/samtools/SAMProgramRecord.java +++ b/src/main/java/htsjdk/samtools/SAMProgramRecord.java @@ -131,4 +131,10 @@ public int hashCode() { Set getStandardTags() { return STANDARD_TAGS; } + + + @Override + public String getSAMString() { + return new SAMTextHeaderCodec().getPGLine(this); + } } diff --git a/src/main/java/htsjdk/samtools/SAMReadGroupRecord.java b/src/main/java/htsjdk/samtools/SAMReadGroupRecord.java index bae3c4f62..14f1c50e3 100644 --- a/src/main/java/htsjdk/samtools/SAMReadGroupRecord.java +++ b/src/main/java/htsjdk/samtools/SAMReadGroupRecord.java @@ -163,5 +163,10 @@ public int hashCode() { Set getStandardTags() { return STANDARD_TAGS; } + + @Override + public String getSAMString() { + return new SAMTextHeaderCodec().getRGLine(this); + } } diff --git a/src/main/java/htsjdk/samtools/SAMSequenceRecord.java b/src/main/java/htsjdk/samtools/SAMSequenceRecord.java index 8e7ccf295..a4b4df236 100644 --- a/src/main/java/htsjdk/samtools/SAMSequenceRecord.java +++ b/src/main/java/htsjdk/samtools/SAMSequenceRecord.java @@ -23,6 +23,9 @@ */ package htsjdk.samtools; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlValue; import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; @@ -32,10 +35,6 @@ import java.util.Set; import java.util.regex.Pattern; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlValue; - /** * Header information about a reference sequence. Corresponds to @SQ header record in SAM text header. */ @@ -246,5 +245,10 @@ public String toString() { getAssembly() ); } + + @Override + public String getSAMString() { + return new SAMTextHeaderCodec().getSQLine(this); + } } diff --git a/src/main/java/htsjdk/samtools/SAMTextHeaderCodec.java b/src/main/java/htsjdk/samtools/SAMTextHeaderCodec.java index fb4b02ac3..402ea3ce8 100644 --- a/src/main/java/htsjdk/samtools/SAMTextHeaderCodec.java +++ b/src/main/java/htsjdk/samtools/SAMTextHeaderCodec.java @@ -429,22 +429,27 @@ private void println(final String s) { } private void writePGLine(final SAMProgramRecord programRecord) { - if (programRecord == null) { - return; - } + println(getPGLine(programRecord)); + } + + protected String getPGLine(final SAMProgramRecord programRecord) { final String[] fields = new String[2 + programRecord.getAttributes().size()]; fields[0] = HEADER_LINE_START + HeaderRecordType.PG; fields[1] = SAMProgramRecord.PROGRAM_GROUP_ID_TAG + TAG_KEY_VALUE_SEPARATOR + programRecord.getProgramGroupId(); encodeTags(programRecord, fields, 2); - println(StringUtil.join(FIELD_SEPARATOR, fields)); + return StringUtil.join(FIELD_SEPARATOR, fields); } private void writeRGLine(final SAMReadGroupRecord readGroup) { - final String[] fields = new String[2 + readGroup.getAttributes().size()]; - fields[0] = HEADER_LINE_START + HeaderRecordType.RG; - fields[1] = SAMReadGroupRecord.READ_GROUP_ID_TAG + TAG_KEY_VALUE_SEPARATOR + readGroup.getReadGroupId(); - encodeTags(readGroup, fields, 2); - println(StringUtil.join(FIELD_SEPARATOR, fields)); + println(getRGLine(readGroup)); + } + + protected String getRGLine(final SAMReadGroupRecord readGroup) { + final String[] fields = new String[2 + readGroup.getAttributes().size()]; + fields[0] = HEADER_LINE_START + HeaderRecordType.RG; + fields[1] = SAMReadGroupRecord.READ_GROUP_ID_TAG + TAG_KEY_VALUE_SEPARATOR + readGroup.getReadGroupId(); + encodeTags(readGroup, fields, 2); + return StringUtil.join(FIELD_SEPARATOR, fields); } private void writeHDLine(final boolean keepExistingVersionNumber) { @@ -470,13 +475,17 @@ private void writeHDLine(final boolean keepExistingVersionNumber) { } private void writeSQLine(final SAMSequenceRecord sequenceRecord) { + println(getSQLine(sequenceRecord)); + } + + protected String getSQLine(final SAMSequenceRecord sequenceRecord) { final int numAttributes = sequenceRecord.getAttributes() != null ? sequenceRecord.getAttributes().size() : 0; final String[] fields = new String[3 + numAttributes]; fields[0] = HEADER_LINE_START + HeaderRecordType.SQ; fields[1] = SAMSequenceRecord.SEQUENCE_NAME_TAG + TAG_KEY_VALUE_SEPARATOR + sequenceRecord.getSequenceName(); fields[2] = SAMSequenceRecord.SEQUENCE_LENGTH_TAG + TAG_KEY_VALUE_SEPARATOR + Integer.toString(sequenceRecord.getSequenceLength()); encodeTags(sequenceRecord, fields, 3); - println(StringUtil.join(FIELD_SEPARATOR, fields)); + return StringUtil.join(FIELD_SEPARATOR, fields); } /** diff --git a/src/test/java/htsjdk/samtools/SAMProgramRecordTest.java b/src/test/java/htsjdk/samtools/SAMProgramRecordTest.java new file mode 100644 index 000000000..5d9a36893 --- /dev/null +++ b/src/test/java/htsjdk/samtools/SAMProgramRecordTest.java @@ -0,0 +1,42 @@ +/* + * The MIT License + * + * Copyright (c) 2017 The Broad Institute + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package htsjdk.samtools; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Test for SAMReadGroupRecordTest + */ +public class SAMProgramRecordTest { + + @Test + public void testGetSAMString() { + SAMProgramRecord r = new SAMProgramRecord("SW-eIV"); + r.setProgramName("telnet"); + r.setProgramVersion("0.17-40"); + r.setCommandLine("telnet towel.blinkenlights.nl"); + Assert.assertEquals("@PG\tID:SW-eIV\tPN:telnet\tVN:0.17-40\tCL:telnet towel.blinkenlights.nl", r.getSAMString()); + } +} diff --git a/src/test/java/htsjdk/samtools/SAMReadGroupRecordTest.java b/src/test/java/htsjdk/samtools/SAMReadGroupRecordTest.java new file mode 100644 index 000000000..c3a7423d3 --- /dev/null +++ b/src/test/java/htsjdk/samtools/SAMReadGroupRecordTest.java @@ -0,0 +1,42 @@ +/* + * The MIT License + * + * Copyright (c) 2017 The Broad Institute + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package htsjdk.samtools; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Test for SAMReadGroupRecordTest + */ +public class SAMReadGroupRecordTest { + + @Test + public void testGetSAMString() { + SAMReadGroupRecord r = new SAMReadGroupRecord("rg1"); + r.setSample("mysample"); + r.setPlatform("ILLUMINA"); + r.setDescription("my description"); + Assert.assertEquals("@RG\tID:rg1\tSM:mysample\tPL:ILLUMINA\tDS:my description", r.getSAMString()); + } +} diff --git a/src/test/java/htsjdk/samtools/SAMSequenceRecordTest.java b/src/test/java/htsjdk/samtools/SAMSequenceRecordTest.java new file mode 100644 index 000000000..1035d1b10 --- /dev/null +++ b/src/test/java/htsjdk/samtools/SAMSequenceRecordTest.java @@ -0,0 +1,42 @@ +/* + * The MIT License + * + * Copyright (c) 2017 The Broad Institute + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package htsjdk.samtools; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Test for SAMReadGroupRecordTest + */ +public class SAMSequenceRecordTest { + + @Test + public void testGetSAMString() { + SAMSequenceRecord r = new SAMSequenceRecord("chr5_but_without_a_prefix", 271828); + r.setSpecies("Psephophorus terrypratchetti"); + r.setAssembly("GRCt01"); + r.setMd5("7a6dd3d307de916b477e7bf304ac22bc"); + Assert.assertEquals("@SQ\tSN:chr5_but_without_a_prefix\tLN:271828\tSP:Psephophorus terrypratchetti\tAS:GRCt01\tM5:7a6dd3d307de916b477e7bf304ac22bc", r.getSAMString()); + } +}