Skip to content

Commit 88b6719

Browse files
magicDGScmnbroad
authored andcommitted
IndexingVariantContextWriter cleanup (#706)
* extract PositionalOutputStream * extract setIndexSequenceDictionary to IndexCreator with no-op default and TribbleIndexCreator implementation
1 parent 224cfc1 commit 88b6719

5 files changed

Lines changed: 152 additions & 52 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2012 The Broad Institute
3+
*
4+
* Permission is hereby granted, free of charge, to any person
5+
* obtaining a copy of this software and associated documentation
6+
* files (the "Software"), to deal in the Software without
7+
* restriction, including without limitation the rights to use,
8+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following
11+
* conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
23+
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
package htsjdk.samtools.util;
27+
28+
import java.io.IOException;
29+
import java.io.OutputStream;
30+
31+
/**
32+
* Wraps output stream in a manner which keeps track of the position within the file and allowing writes
33+
* at arbitrary points
34+
*/
35+
public final class PositionalOutputStream extends OutputStream implements LocationAware
36+
{
37+
private final OutputStream out;
38+
private long position = 0;
39+
40+
public PositionalOutputStream(final OutputStream out) {
41+
this.out = out;
42+
}
43+
44+
public final void write(final byte[] bytes) throws IOException {
45+
write(bytes, 0, bytes.length);
46+
}
47+
48+
public final void write(final byte[] bytes, final int startIndex, final int numBytes) throws IOException {
49+
position += numBytes;
50+
out.write(bytes, startIndex, numBytes);
51+
}
52+
53+
public final void write(final int c) throws IOException {
54+
position++;
55+
out.write(c);
56+
}
57+
58+
public final long getPosition() { return position; }
59+
60+
@Override
61+
public void close() throws IOException {
62+
super.close();
63+
out.close();
64+
}
65+
}

src/main/java/htsjdk/tribble/index/IndexCreator.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424
package htsjdk.tribble.index;
2525

26+
import htsjdk.samtools.SAMSequenceDictionary;
2627
import htsjdk.tribble.Feature;
2728

2829
/**
@@ -45,6 +46,12 @@ public interface IndexCreator {
4546
* @return an index object
4647
*/
4748
public Index finalizeIndex(long finalFilePosition);
49+
50+
/**
51+
* Set the sequence dictionary for the index. Default implementation does nothing.
52+
* @param dict the dictionary to add to the index.
53+
*/
54+
public default void setIndexSequenceDictionary(final SAMSequenceDictionary dict) { }
4855
}
4956

5057

src/main/java/htsjdk/tribble/index/TribbleIndexCreator.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,31 @@
2323
*/
2424
package htsjdk.tribble.index;
2525

26+
import htsjdk.samtools.SAMSequenceDictionary;
27+
import htsjdk.samtools.SAMSequenceRecord;
28+
2629
import java.util.LinkedHashMap;
2730

2831
/**
2932
* Base class for Tribble-specific index creators.
3033
*/
3134
public abstract class TribbleIndexCreator implements IndexCreator {
35+
// a constant we use for marking sequence dictionary entries in the Tribble index property list
36+
private static final String SEQUENCE_DICTIONARY_PROPERTY_PREDICATE = "DICT:";
37+
3238
protected LinkedHashMap<String, String> properties = new LinkedHashMap<String, String>();
3339

3440
public void addProperty(final String key, final String value) {
3541
properties.put(key, value);
3642
}
43+
44+
/** Set the sequence dictionary entries for the index property list. */
45+
@Override
46+
public void setIndexSequenceDictionary(final SAMSequenceDictionary dict) {
47+
for (final SAMSequenceRecord seq : dict.getSequences()) {
48+
final String contig = SEQUENCE_DICTIONARY_PROPERTY_PREDICATE + seq.getSequenceName();
49+
final String length = String.valueOf(seq.getSequenceLength());
50+
addProperty(contig,length);
51+
}
52+
}
3753
}

src/main/java/htsjdk/variant/variantcontext/writer/IndexingVariantContextWriter.java

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,13 @@
2626
package htsjdk.variant.variantcontext.writer;
2727

2828
import htsjdk.samtools.SAMSequenceDictionary;
29-
import htsjdk.samtools.SAMSequenceRecord;
3029
import htsjdk.samtools.util.LocationAware;
3130
import htsjdk.samtools.util.RuntimeIOException;
3231
import htsjdk.tribble.index.DynamicIndexCreator;
3332
import htsjdk.tribble.index.Index;
3433
import htsjdk.tribble.index.IndexCreator;
3534
import htsjdk.tribble.index.IndexFactory;
36-
import htsjdk.tribble.index.TribbleIndexCreator;
35+
import htsjdk.samtools.util.PositionalOutputStream;
3736
import htsjdk.variant.variantcontext.VariantContext;
3837
import htsjdk.variant.vcf.VCFHeader;
3938

@@ -139,9 +138,7 @@ public void close() {
139138

140139
// close the index stream (keep it separate to help debugging efforts)
141140
if (indexer != null) {
142-
if (indexer instanceof TribbleIndexCreator) {
143-
setIndexSequenceDictionary((TribbleIndexCreator)indexer, refDict);
144-
}
141+
indexer.setIndexSequenceDictionary(refDict);
145142
final Index index = indexer.finalizeIndex(locationSource.getPosition());
146143
index.writeBasedOnFeatureFile(location);
147144
}
@@ -180,51 +177,4 @@ public void add(final VariantContext vc) {
180177
protected static final String writerName(final File location, final OutputStream stream) {
181178
return location == null ? stream.toString() : location.getAbsolutePath();
182179
}
183-
184-
// a constant we use for marking sequence dictionary entries in the Tribble index property list
185-
private static final String SequenceDictionaryPropertyPredicate = "DICT:";
186-
187-
private static void setIndexSequenceDictionary(final TribbleIndexCreator indexCreator, final SAMSequenceDictionary dict) {
188-
for (final SAMSequenceRecord seq : dict.getSequences()) {
189-
final String contig = SequenceDictionaryPropertyPredicate + seq.getSequenceName();
190-
final String length = String.valueOf(seq.getSequenceLength());
191-
indexCreator.addProperty(contig,length);
192-
}
193-
}
194-
}
195-
196-
/**
197-
* Wraps output stream in a manner which keeps track of the position within the file and allowing writes
198-
* at arbitrary points
199-
*/
200-
final class PositionalOutputStream extends OutputStream implements LocationAware
201-
{
202-
private final OutputStream out;
203-
private long position = 0;
204-
205-
public PositionalOutputStream(final OutputStream out) {
206-
this.out = out;
207-
}
208-
209-
public final void write(final byte[] bytes) throws IOException {
210-
write(bytes, 0, bytes.length);
211-
}
212-
213-
public final void write(final byte[] bytes, final int startIndex, final int numBytes) throws IOException {
214-
position += numBytes;
215-
out.write(bytes, startIndex, numBytes);
216-
}
217-
218-
public final void write(final int c) throws IOException {
219-
position++;
220-
out.write(c);
221-
}
222-
223-
public final long getPosition() { return position; }
224-
225-
@Override
226-
public void close() throws IOException {
227-
super.close();
228-
out.close();
229-
}
230180
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2015 Daniel Gómez-Sánchez
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
package htsjdk.samtools.util;
26+
27+
import org.testng.Assert;
28+
import org.testng.annotations.Test;
29+
30+
import java.io.IOException;
31+
import java.io.OutputStream;
32+
33+
/**
34+
* @author Daniel Gomez-Sanchez (magicDGS)
35+
*/
36+
public class PositionalOutputStreamTest {
37+
38+
@Test
39+
public void basicPositionTest() throws Exception {
40+
// wrapped null output stream to check
41+
final PositionalOutputStream wrapped = new PositionalOutputStream(new OutputStream() {
42+
@Override
43+
public void write(int b) throws IOException {}
44+
});
45+
int position = 0;
46+
// check that we start at position 0
47+
Assert.assertEquals(wrapped.getPosition(), position);
48+
// check that write one int just add one
49+
wrapped.write(100);
50+
Assert.assertEquals(wrapped.getPosition(), ++position);
51+
// check that write a byte array adds its length
52+
final byte[] bytes = new byte[]{1, 3, 5, 7};
53+
wrapped.write(bytes);
54+
position += bytes.length;
55+
Assert.assertEquals(wrapped.getPosition(), position);
56+
// check that write just some bytes from an array adds its length
57+
wrapped.write(bytes, 2, 2);
58+
position += 2;
59+
Assert.assertEquals(wrapped.getPosition(), position);
60+
}
61+
62+
}

0 commit comments

Comments
 (0)