diff --git a/src/main/java/htsjdk/tribble/TabixFeatureReader.java b/src/main/java/htsjdk/tribble/TabixFeatureReader.java index 889fdc22b..e72243325 100644 --- a/src/main/java/htsjdk/tribble/TabixFeatureReader.java +++ b/src/main/java/htsjdk/tribble/TabixFeatureReader.java @@ -23,7 +23,6 @@ */ package htsjdk.tribble; -import htsjdk.samtools.seekablestream.SeekableStreamFactory; import htsjdk.samtools.util.BlockCompressedInputStream; import htsjdk.samtools.util.RuntimeIOException; import htsjdk.tribble.readers.*; diff --git a/src/main/java/htsjdk/tribble/Tribble.java b/src/main/java/htsjdk/tribble/Tribble.java index 468f55d77..f2c07a248 100644 --- a/src/main/java/htsjdk/tribble/Tribble.java +++ b/src/main/java/htsjdk/tribble/Tribble.java @@ -27,6 +27,7 @@ import htsjdk.tribble.util.TabixUtils; import java.io.File; +import java.nio.file.Path; /** * Common, tribble wide constants and static functions @@ -37,9 +38,9 @@ private Tribble() { } // can't be instantiated public final static String STANDARD_INDEX_EXTENSION = ".idx"; /** - * Return the name of the index file for the provided vcf {@code filename} + * Return the name of the index file for the provided {@code filename} * Does not actually create an index - * @param filename name of the vcf file + * @param filename name of the file * @return non-null String representing the index filename */ public static String indexFile(final String filename) { @@ -47,9 +48,9 @@ public static String indexFile(final String filename) { } /** - * Return the File of the index file for the provided vcf {@code file} + * Return the File of the index file for the provided {@code file} * Does not actually create an index - * @param file the vcf file + * @param file the file * @return a non-null File representing the index */ public static File indexFile(final File file) { @@ -57,9 +58,19 @@ public static File indexFile(final File file) { } /** - * Return the name of the tabix index file for the provided vcf {@code filename} + * Return the name of the index file for the provided {@code path} * Does not actually create an index - * @param filename name of the vcf file + * @param path the path + * @return Path representing the index filename + */ + public static Path indexPath(final Path path) { + return path.getFileSystem().getPath(indexFile(path.toAbsolutePath().toString())); + } + + /** + * Return the name of the tabix index file for the provided {@code filename} + * Does not actually create an index + * @param filename name of the file * @return non-null String representing the index filename */ public static String tabixIndexFile(final String filename) { @@ -67,9 +78,9 @@ public static String tabixIndexFile(final String filename) { } /** - * Return the File of the tabix index file for the provided vcf {@code file} + * Return the File of the tabix index file for the provided {@code file} * Does not actually create an index - * @param file the vcf file + * @param file the file * @return a non-null File representing the index */ public static File tabixIndexFile(final File file) { @@ -77,9 +88,19 @@ public static File tabixIndexFile(final File file) { } /** - * Return the name of the index file for the provided vcf {@code filename} and {@code extension} + * Return the name of the tabix index file for the provided {@code path} + * Does not actually create an index + * @param path the path + * @return Path representing the index filename + */ + public static Path tabixIndexPath(final Path path) { + return path.getFileSystem().getPath(tabixIndexFile(path.toAbsolutePath().toString())); + } + + /** + * Return the name of the index file for the provided {@code filename} and {@code extension} * Does not actually create an index - * @param filename name of the vcf file + * @param filename name of the file * @param extension the extension to use for the index * @return non-null String representing the index filename */ @@ -88,9 +109,9 @@ private static String indexFile(final String filename, final String extension) { } /** - * Return the File of the index file for the provided vcf {@code file} and {@code extension} + * Return the File of the index file for the provided {@code file} and {@code extension} * Does not actually create an index - * @param file the vcf file + * @param file the file * @param extension the extension to use for the index * @return a non-null File representing the index */ diff --git a/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java b/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java index 365cc281a..7c39faa04 100644 --- a/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java +++ b/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java @@ -33,11 +33,9 @@ import htsjdk.tribble.util.ParsingUtils; import java.io.BufferedInputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; -import java.net.URISyntaxException; import java.net.URLEncoder; import java.nio.channels.SeekableByteChannel; import java.util.ArrayList; diff --git a/src/main/java/htsjdk/tribble/index/AbstractIndex.java b/src/main/java/htsjdk/tribble/index/AbstractIndex.java index 5ae5492d6..b1cc1364c 100644 --- a/src/main/java/htsjdk/tribble/index/AbstractIndex.java +++ b/src/main/java/htsjdk/tribble/index/AbstractIndex.java @@ -18,6 +18,9 @@ package htsjdk.tribble.index; +import htsjdk.samtools.util.IOUtil; +import htsjdk.samtools.util.Log; +import htsjdk.samtools.util.RuntimeIOException; import htsjdk.tribble.Tribble; import htsjdk.tribble.TribbleException; import htsjdk.tribble.util.LittleEndianInputStream; @@ -25,8 +28,9 @@ import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -67,11 +71,12 @@ private final static long NO_TS = -1L; protected int version; // Our version value - protected File indexedFile = null; // The file we've created this index for + protected Path indexedPath = null; // The file we've created this index for protected long indexedFileSize = NO_FILE_SIZE; // The size of the indexed file protected long indexedFileTS = NO_TS; // The timestamp protected String indexedFileMD5 = NO_MD5; // The MD5 value, generally not filled in (expensive to calc) protected int flags; + protected final Log logger = Log.getInstance(this.getClass()); public boolean hasFileSize() { return indexedFileSize != NO_FILE_SIZE; @@ -116,8 +121,8 @@ public boolean equalsIgnoreProperties(final Object obj) { return false; } - if (indexedFile != other.indexedFile && (indexedFile == null || !indexedFile.equals(other.indexedFile))) { - System.err.printf("equals indexedFile: this %s != other %s%n", indexedFile, other.indexedFile); + if (indexedPath != other.indexedPath && (indexedPath == null || !indexedPath.equals(other.indexedPath))) { + System.err.printf("equals indexedPath: this %s != other %s%n", indexedPath, other.indexedPath); return false; } @@ -159,18 +164,27 @@ public AbstractIndex() { * @param featureFile the feature file to create an index from */ public AbstractIndex(final String featureFile) { - this(new File(featureFile)); + this(); + try { + this.indexedPath = IOUtil.getPath(featureFile).toAbsolutePath(); + } catch (IOException e) { + throw new IllegalArgumentException("IO error: " + e.getMessage(), e); + } } public AbstractIndex(final File featureFile) { + this(featureFile.toPath()); + } + + public AbstractIndex(final Path featurePath) { this(); - this.indexedFile = featureFile; + this.indexedPath = featurePath.toAbsolutePath(); } public AbstractIndex(final AbstractIndex parent) { this(); this.version = parent.version; - this.indexedFile = parent.indexedFile; + this.indexedPath = parent.indexedPath; this.indexedFileSize = parent.indexedFileSize; this.indexedFileTS = parent.indexedFileTS; this.indexedFileMD5 = parent.indexedFileMD5; @@ -200,8 +214,18 @@ public boolean isCurrentVersion() { return version == VERSION; } + /** + * Gets the indexed file. + * @throws UnsupportedOperationException if the path cannot be represented as a file. + * @deprecated on 03/2017. Use {@link #getIndexedPath()} instead. + */ + @Deprecated public File getIndexedFile() { - return indexedFile; + return getIndexedPath().toFile(); + } + + public Path getIndexedPath() { + return indexedPath; } public long getIndexedFileSize() { @@ -234,10 +258,14 @@ public boolean containsChromosome(final String chr) { } public void finalizeIndex() { - // these two functions must be called now because the file may be being written during on the fly indexing - if (indexedFile != null) { - this.indexedFileSize = indexedFile.length(); - this.indexedFileTS = indexedFile.lastModified(); + try { + // these two functions must be called now because the file may be being written during on the fly indexing + if (indexedPath != null) { + this.indexedFileSize = Files.size(indexedPath); + this.indexedFileTS = Files.getLastModifiedTime(indexedPath).toMillis(); + } + } catch (IOException e) { + throw new RuntimeIOException(e); } } @@ -251,7 +279,7 @@ private void writeHeader(final LittleEndianOutputStream dos) throws IOException dos.writeInt(MAGIC_NUMBER); dos.writeInt(getType()); dos.writeInt(version); - dos.writeString(indexedFile.getAbsolutePath()); + dos.writeString(indexedPath.toUri().toString()); dos.writeLong(indexedFileSize); dos.writeLong(indexedFileTS); dos.writeString(indexedFileMD5); @@ -274,7 +302,7 @@ private void writeHeader(final LittleEndianOutputStream dos) throws IOException private void readHeader(final LittleEndianInputStream dis) throws IOException { version = dis.readInt(); - indexedFile = new File(dis.readString()); + indexedPath = IOUtil.getPath(dis.readString()); indexedFileSize = dis.readLong(); indexedFileTS = dis.readLong(); indexedFileMD5 = dis.readString(); @@ -349,18 +377,22 @@ public void write(final LittleEndianOutputStream stream) throws IOException { } @Override - public void write(final File idxFile) throws IOException { - try(final LittleEndianOutputStream idxStream = new LittleEndianOutputStream(new BufferedOutputStream(new FileOutputStream(idxFile)))) { + public void write(final Path idxPath) throws IOException { + try(final LittleEndianOutputStream idxStream = new LittleEndianOutputStream(new BufferedOutputStream(Files.newOutputStream(idxPath)))) { write(idxStream); } } @Override - public void writeBasedOnFeatureFile(final File featureFile) throws IOException { - if (!featureFile.isFile()) return; - write(Tribble.indexFile(featureFile)); + public void writeBasedOnFeaturePath(final Path featurePath) throws IOException { + if (!Files.isRegularFile(featurePath)) { + logger.warn("Index not written into ", featurePath); + return; + } + write(Tribble.indexPath(featurePath)); } + public void read(final LittleEndianInputStream dis) throws IOException { try { readHeader(dis); @@ -386,7 +418,7 @@ public void read(final LittleEndianInputStream dis) throws IOException { } protected void printIndexInfo() { - System.out.println(String.format("Index for %s with %d indices", indexedFile, chrIndices.size())); + System.out.println(String.format("Index for %s with %d indices", indexedPath, chrIndices.size())); final BlockStats stats = getBlockStats(true); System.out.println(String.format(" total blocks %d", stats.total)); System.out.println(String.format(" total empty blocks %d", stats.empty)); diff --git a/src/main/java/htsjdk/tribble/index/DynamicIndexCreator.java b/src/main/java/htsjdk/tribble/index/DynamicIndexCreator.java index 3552fbb4f..17274ace6 100644 --- a/src/main/java/htsjdk/tribble/index/DynamicIndexCreator.java +++ b/src/main/java/htsjdk/tribble/index/DynamicIndexCreator.java @@ -31,6 +31,7 @@ import htsjdk.tribble.util.MathUtils; import java.io.File; +import java.nio.file.Path; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -56,13 +57,15 @@ MathUtils.RunningStat stats = new MathUtils.RunningStat(); long basesSeen = 0; Feature lastFeature = null; - File inputFile; - public DynamicIndexCreator(final File inputFile, final IndexFactory.IndexBalanceApproach iba) { + public DynamicIndexCreator(final Path inputPath, final IndexFactory.IndexBalanceApproach iba) { this.iba = iba; // get a list of index creators - this.inputFile = inputFile; - creators = getIndexCreators(inputFile,iba); + creators = getIndexCreators(inputPath, iba); + } + + public DynamicIndexCreator(final File inputFile, final IndexFactory.IndexBalanceApproach iba) { + this(inputFile.toPath(), iba); } @Override @@ -90,19 +93,19 @@ public Index finalizeIndex(final long finalFilePosition) { /** * create a list of index creators (initialized) representing the common index types we'd suspect they'd like to use - * @param inputFile the input file to use to create the indexes + * @param inputPath the input path to use to create the indexes * @return a map of index type to the best index for that balancing approach */ - private Map getIndexCreators(final File inputFile, final IndexFactory.IndexBalanceApproach iba) { + private Map getIndexCreators(final Path inputPath, final IndexFactory.IndexBalanceApproach iba) { final Map creators = new HashMap(); if (iba == IndexFactory.IndexBalanceApproach.FOR_SIZE) { // add a linear index with the default bin size - final LinearIndexCreator linearNormal = new LinearIndexCreator(inputFile, LinearIndexCreator.DEFAULT_BIN_WIDTH); + final LinearIndexCreator linearNormal = new LinearIndexCreator(inputPath, LinearIndexCreator.DEFAULT_BIN_WIDTH); creators.put(IndexFactory.IndexType.LINEAR,linearNormal); // create a tree index with the default size - final IntervalIndexCreator treeNormal = new IntervalIndexCreator(inputFile, IntervalIndexCreator.DEFAULT_FEATURE_COUNT); + final IntervalIndexCreator treeNormal = new IntervalIndexCreator(inputPath, IntervalIndexCreator.DEFAULT_FEATURE_COUNT); creators.put(IndexFactory.IndexType.INTERVAL_TREE,treeNormal); } @@ -111,12 +114,12 @@ public Index finalizeIndex(final long finalFilePosition) { if (iba == IndexFactory.IndexBalanceApproach.FOR_SEEK_TIME) { // create a linear index with a small bin size final LinearIndexCreator linearSmallBin = - new LinearIndexCreator(inputFile, Math.max(200, LinearIndexCreator.DEFAULT_BIN_WIDTH / 4)); + new LinearIndexCreator(inputPath, Math.max(200, LinearIndexCreator.DEFAULT_BIN_WIDTH / 4)); creators.put(IndexFactory.IndexType.LINEAR,linearSmallBin); // create a tree index with a small index size final IntervalIndexCreator treeSmallBin = - new IntervalIndexCreator(inputFile, Math.max(20, IntervalIndexCreator.DEFAULT_FEATURE_COUNT / 8)); + new IntervalIndexCreator(inputPath, Math.max(20, IntervalIndexCreator.DEFAULT_FEATURE_COUNT / 8)); creators.put(IndexFactory.IndexType.INTERVAL_TREE,treeSmallBin); } diff --git a/src/main/java/htsjdk/tribble/index/Index.java b/src/main/java/htsjdk/tribble/index/Index.java index ca6cc60d3..c5a63ff6e 100644 --- a/src/main/java/htsjdk/tribble/index/Index.java +++ b/src/main/java/htsjdk/tribble/index/Index.java @@ -27,6 +27,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -72,17 +73,42 @@ /** * Writes the index into a file. * + * Default implementation delegates to {@link #write(Path)} + * * @param idxFile Where to write the index. * @throws IOException if the index is unable to write to the specified file */ - public void write(final File idxFile) throws IOException; + public default void write(final File idxFile) throws IOException { + write(idxFile.toPath()); + } + + /** + * Writes the index into a path. + * + * @param indexPath Where to write the index. + * @throws IOException if the index is unable to write to the specified path. + */ + public void write(final Path indexPath) throws IOException; /** * Write an appropriately named and located Index file based on the name and location of the featureFile. * If featureFile is not a normal file, the index will silently not be written. + * + * Default implementation delegates to {@link #writeBasedOnFeaturePath(Path)} + * * @param featureFile */ - public void writeBasedOnFeatureFile(File featureFile) throws IOException; + public default void writeBasedOnFeatureFile(File featureFile) throws IOException { + writeBasedOnFeaturePath(featureFile.toPath()); + } + + /** + * Write an appropriately named and located Index file based on the name and location of the featureFile. + * If featureFile is not a normal file, the index will silently not be written. + * + * @param featurePath + */ + public void writeBasedOnFeaturePath(Path featurePath) throws IOException; /** * @return get the list of properties for this index. Returns null if no properties. diff --git a/src/main/java/htsjdk/tribble/index/interval/IntervalIndexCreator.java b/src/main/java/htsjdk/tribble/index/interval/IntervalIndexCreator.java index 01219040c..58e2f87ee 100644 --- a/src/main/java/htsjdk/tribble/index/interval/IntervalIndexCreator.java +++ b/src/main/java/htsjdk/tribble/index/interval/IntervalIndexCreator.java @@ -25,6 +25,7 @@ import htsjdk.tribble.index.interval.IntervalTreeIndex.ChrIndex; import java.io.File; +import java.nio.file.Path; import java.util.ArrayList; import java.util.LinkedList; @@ -51,15 +52,23 @@ private final ArrayList intervals = new ArrayList(); - File inputFile; + Path inputPath; - public IntervalIndexCreator(final File inputFile, final int featuresPerInterval) { - this.inputFile = inputFile; + public IntervalIndexCreator(final Path inputPath, final int featuresPerInterval) { + this.inputPath = inputPath; this.featuresPerInterval = featuresPerInterval; } + public IntervalIndexCreator(final File inputFile, final int featuresPerInterval) { + this(inputFile.toPath(), featuresPerInterval); + } + public IntervalIndexCreator(final File inputFile) { - this(inputFile, DEFAULT_FEATURE_COUNT); + this(inputFile.toPath()); + } + + public IntervalIndexCreator(final Path inputPath) { + this(inputPath, DEFAULT_FEATURE_COUNT); } @Override @@ -108,7 +117,7 @@ private void addIntervalsToLastChr(final long currentPos) { */ @Override public Index finalizeIndex(final long finalFilePosition) { - final IntervalTreeIndex featureIndex = new IntervalTreeIndex(inputFile.getAbsolutePath()); + final IntervalTreeIndex featureIndex = new IntervalTreeIndex(inputPath); // dump the remaining bins to the index addIntervalsToLastChr(finalFilePosition); featureIndex.setChrIndex(chrList); diff --git a/src/main/java/htsjdk/tribble/index/interval/IntervalTreeIndex.java b/src/main/java/htsjdk/tribble/index/interval/IntervalTreeIndex.java index 9a4206ebf..c4b2865dc 100644 --- a/src/main/java/htsjdk/tribble/index/interval/IntervalTreeIndex.java +++ b/src/main/java/htsjdk/tribble/index/interval/IntervalTreeIndex.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.InputStream; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -57,6 +58,15 @@ public IntervalTreeIndex(final InputStream inputStream) throws IOException { * * @param featureFile File which we are indexing */ + public IntervalTreeIndex(final Path featureFile) { + super(featureFile); + } + + /** + * Prepare to build an index. + * + * @param featureFile File which we are indexing + */ public IntervalTreeIndex(final String featureFile) { super(featureFile); } diff --git a/src/main/java/htsjdk/tribble/index/linear/LinearIndex.java b/src/main/java/htsjdk/tribble/index/linear/LinearIndex.java index 5047ab61a..3d7905af1 100644 --- a/src/main/java/htsjdk/tribble/index/linear/LinearIndex.java +++ b/src/main/java/htsjdk/tribble/index/linear/LinearIndex.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -71,12 +72,21 @@ * @param indices * @param featureFile */ - public LinearIndex(final List indices, final File featureFile) { - super(featureFile.getAbsolutePath()); + public LinearIndex(final List indices, final Path featureFile) { + super(featureFile); for (final ChrIndex index : indices) chrIndices.put(index.getName(), index); } + /** + * Initialize using the specified {@code indices} + * @param indices + * @param featureFile + */ + public LinearIndex(final List indices, final File featureFile) { + this(indices, featureFile.toPath()); + } + private LinearIndex(final LinearIndex parent, final List indices) { super(parent); for (final ChrIndex index : indices) @@ -92,6 +102,14 @@ public LinearIndex(final String featureFile) { } /** + * Initialize with default parameters + * @param featurePath Path for which this is an index + */ + public LinearIndex(final Path featurePath) { + super(featurePath); + } + + /** * Load from file. * @param inputStream This method assumes that the input stream is already buffered as appropriate. */ diff --git a/src/main/java/htsjdk/tribble/index/linear/LinearIndexCreator.java b/src/main/java/htsjdk/tribble/index/linear/LinearIndexCreator.java index daad6cce6..9109705d2 100644 --- a/src/main/java/htsjdk/tribble/index/linear/LinearIndexCreator.java +++ b/src/main/java/htsjdk/tribble/index/linear/LinearIndexCreator.java @@ -29,6 +29,7 @@ import htsjdk.tribble.index.TribbleIndexCreator; import java.io.File; +import java.nio.file.Path; import java.util.ArrayList; import java.util.LinkedList; @@ -43,20 +44,28 @@ private int binWidth = DEFAULT_BIN_WIDTH; // the input file - private final File inputFile; + private final Path inputFile; private final LinkedList chrList = new LinkedList(); private int longestFeature= 0; private final ArrayList blocks = new ArrayList(); - public LinearIndexCreator(final File inputFile, final int binSize) { - this.inputFile = inputFile; + public LinearIndexCreator(final Path inputPath, final int binSize) { + this.inputFile = inputPath; binWidth = binSize; } + public LinearIndexCreator(final File inputFile, final int binSize) { + this(inputFile.toPath(), binSize); + } + public LinearIndexCreator(final File inputFile) { - this(inputFile, DEFAULT_BIN_WIDTH); + this(inputFile.toPath()); + } + + public LinearIndexCreator(final Path inputPath) { + this(inputPath, DEFAULT_BIN_WIDTH); } /** diff --git a/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java b/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java index 044cefe61..43b1a2b40 100644 --- a/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java +++ b/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java @@ -30,7 +30,10 @@ import htsjdk.samtools.util.BlockCompressedInputStream; import htsjdk.samtools.util.BlockCompressedOutputStream; import htsjdk.samtools.util.CloserUtil; +import htsjdk.samtools.util.IOUtil; +import htsjdk.samtools.util.Log; import htsjdk.samtools.util.StringUtil; +import htsjdk.tribble.Tribble; import htsjdk.tribble.TribbleException; import htsjdk.tribble.index.Block; import htsjdk.tribble.index.Index; @@ -44,6 +47,8 @@ import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; /** @@ -61,6 +66,8 @@ MAGIC_NUMBER = bb.order(ByteOrder.LITTLE_ENDIAN).getInt(); } + private static final Log LOGGER = Log.getInstance(TabixIndex.class); + private final TabixFormat formatSpec; private final List sequenceNames; private final BinningIndexContent[] indices; @@ -95,6 +102,13 @@ public TabixIndex(final File tabixFile) throws IOException { this(new BlockCompressedInputStream(tabixFile), true); } + /** + * Convenient ctor that opens the path, wraps with with BGZF reader, and closes after reading index. + */ + public TabixIndex(final Path tabixPath) throws IOException { + this(new BlockCompressedInputStream(Files.newInputStream(tabixPath)), true); + } + private TabixIndex(final InputStream inputStream, final boolean closeInputStream) throws IOException { final LittleEndianInputStream dis = new LittleEndianInputStream(inputStream); if (dis.readInt() != MAGIC_NUMBER) { @@ -199,24 +213,27 @@ public TabixFormat getFormatSpec() { /** * Writes the index with BGZF. * - * @param tabixFile Where to write the index. + * @param tabixPath Where to write the index. */ @Override - public void write(final File tabixFile) throws IOException { - try(final LittleEndianOutputStream los = new LittleEndianOutputStream(new BlockCompressedOutputStream(tabixFile))) { + public void write(final Path tabixPath) throws IOException { + try(final LittleEndianOutputStream los = new LittleEndianOutputStream(new BlockCompressedOutputStream(Files.newOutputStream(tabixPath), null))) { write(los); } } /** - * Writes to a file with appropriate name and directory based on feature file. + * Writes to a path with appropriate name and directory based on feature path. * - * @param featureFile File being indexed. + * @param featurePath Path being indexed. */ @Override - public void writeBasedOnFeatureFile(final File featureFile) throws IOException { - if (!featureFile.isFile()) return; - write(new File(featureFile.getAbsolutePath() + TabixUtils.STANDARD_INDEX_EXTENSION)); + public void writeBasedOnFeaturePath(final Path featurePath) throws IOException { + if (!Files.isRegularFile(featurePath)) { + LOGGER.warn("Index not written into ", featurePath); + return; + } + write(Tribble.tabixIndexPath(featurePath)); } /** diff --git a/src/test/java/htsjdk/tribble/index/IndexTest.java b/src/test/java/htsjdk/tribble/index/IndexTest.java index aa179a9a2..56200e672 100644 --- a/src/test/java/htsjdk/tribble/index/IndexTest.java +++ b/src/test/java/htsjdk/tribble/index/IndexTest.java @@ -1,10 +1,14 @@ package htsjdk.tribble.index; +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; import htsjdk.samtools.util.IOUtil; +import htsjdk.tribble.AbstractFeatureReader; import htsjdk.tribble.FeatureCodec; import htsjdk.tribble.TestUtils; import htsjdk.tribble.Tribble; import htsjdk.tribble.bed.BEDCodec; +import htsjdk.tribble.index.interval.IntervalTreeIndex; import htsjdk.tribble.index.linear.LinearIndex; import htsjdk.tribble.index.tabix.TabixFormat; import htsjdk.tribble.index.tabix.TabixIndex; @@ -18,6 +22,11 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.net.URISyntaxException; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -94,4 +103,27 @@ public void testWriteIndex(final File inputFile, final IndexFactory.IndexType ty index.write(new LittleEndianOutputStream(nullOutputStrem)); } + @Test(dataProvider = "writeIndexData") + public void testWritePathIndex(final File inputFile, final IndexFactory.IndexType type, final FeatureCodec codec) throws Exception { + try (final FileSystem fs = Jimfs.newFileSystem("test", Configuration.unix())) { + // create the index + final Index index = IndexFactory.createIndex(inputFile, codec, type); + final Path path = fs.getPath(inputFile.getName() + ".index"); + // write the index to a file + index.write(path); + + // test if the index does not blow up with the path constructor + switch (type) { + case TABIX: + new TabixIndex(path); + break; + case LINEAR: + new LinearIndex(path); + break; + case INTERVAL_TREE: + new IntervalTreeIndex(path); + break; + } + } + } }