package com.github.lindenb.jvarkit.util.tabix; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Iterator; import java.util.Set; import java.util.logging.Logger; import com.github.lindenb.jvarkit.util.vcf.VCFUtils; import htsjdk.samtools.util.AbstractIterator; import htsjdk.samtools.util.RuntimeIOException; import htsjdk.tribble.readers.TabixReader; /** * Safe wrapper around org.broad.tribble.readers.TabixReader (won't return a null iterator ) * @author lindenb * */ public class TabixFileReader implements Closeable //,Iterable<VariantContext> NO, not a true iterator { private static final Logger LOG=Logger.getLogger("jvarkit"); private TabixReader tabix=null; private final String uri; /** return true if 'f' is a file, path ends with '.gz' and there is an associated .tbi file */ public static final boolean isValidTabixFile(final File f) { return VCFUtils.isTabixVcfFile(f); } public TabixFileReader(final String uri) throws IOException { this.uri=uri; this.tabix=new TabixReader(uri); } public TabixFileReader(final String uri,final String idxFn) throws IOException { this.uri=uri; this.tabix=new TabixReader(uri,idxFn); } public TabixReader getTabix() { return tabix; } public Set<String> getChromosomes() { return getTabix().getChromosomes(); } public String getURI() { return this.uri; } public String readLine() throws IOException { if(isClosed()) return null; return this.tabix.readLine(); } protected int[] _parseReg(final String rgn) { if(isClosed()) return null; final int parseReg[]=this.tabix.parseReg(rgn); if(parseReg==null || parseReg.length!=3 || parseReg[0]==-1 || parseReg[1]>parseReg[2]) { if(parseReg[0]==-1) { LOG.warning("unknown chromosome in \""+rgn+"\". Available are: "+getChromosomes()); } LOG.warning("cannot parse region "+rgn); return null; } return parseReg; } public Iterator<String> iterator(final String chrom) { if(isClosed()) return Collections.emptyIterator(); return iterator(_parseReg(chrom)); } public Iterator<String> iterator(final String chrom,final int start) { if(isClosed()) return Collections.emptyIterator(); return iterator(_parseReg(chrom+":"+start)); } public Iterator<String> iterator(final String chrom,final int start ,final int end) { if(isClosed()) return Collections.emptyIterator(); return iterator(_parseReg(chrom+":"+start+"-"+end)); } private Iterator<String> iterator(int parseReg[]) { if(isClosed()) return Collections.emptyIterator(); if(parseReg==null) { return Collections.emptyIterator(); } final TabixReader.Iterator titer=this.tabix.query(parseReg[0], parseReg[1],parseReg[2]); if(titer==null) { return Collections.emptyIterator(); } return new MyIterator(titer); } @Override public void close() { if(tabix!=null) this.tabix.close(); tabix=null; } public boolean isClosed() { return tabix==null; } private class MyIterator extends AbstractIterator<String> { TabixReader.Iterator delegate; MyIterator(final TabixReader.Iterator delegate) { this.delegate=delegate; } @Override protected String advance() { try { if(isClosed() || delegate==null ) return null; final String s= delegate.next(); if(s==null ) delegate=null; return s; } catch(final IOException err) { throw new RuntimeIOException(err); } } } @Override public String toString() { return getURI(); } }