// Copyright (c) 2013 Aalto University // // 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 org.seqdoop.hadoop_bam; import java.io.UnsupportedEncodingException; import java.util.List; import htsjdk.tribble.readers.LineIterator; import htsjdk.variant.variantcontext.Allele; import htsjdk.variant.variantcontext.LazyGenotypesContext; import htsjdk.variant.vcf.AbstractVCFCodec; import htsjdk.variant.vcf.VCFHeader; import htsjdk.variant.vcf.VCFHeaderLine; import htsjdk.variant.vcf.VCFHeaderVersion; // File created: 2013-07-03 15:41:21 // The actual parsing is delegated to AbstractVCFCodec. public class LazyVCFGenotypesContext extends LazyParsingGenotypesContext { /** Takes ownership of the given byte[]: don't modify its contents. */ public LazyVCFGenotypesContext( List<Allele> alleles, String chrom, int start, byte[] utf8Unparsed, int count) { super(new Parser(alleles, chrom, start), utf8Unparsed, count); } public static class HeaderDataCache implements LazyParsingGenotypesContext.HeaderDataCache { private HeaderSettableVCFCodec codec = new HeaderSettableVCFCodec(); @Override public void setHeader(VCFHeader header) { VCFHeaderVersion version = null; // Normally AbstractVCFCodec parses the header and thereby sets the // version field. It gets used later on so we need to set it. for (final VCFHeaderLine line : header.getMetaDataInInputOrder()) { if (VCFHeaderVersion.isFormatString(line.getKey())) { version = VCFHeaderVersion.toHeaderVersion(line.getValue()); break; } } codec.setHeaderAndVersion(header, version); } public AbstractVCFCodec getCodec() { return codec; } } public static class Parser extends LazyParsingGenotypesContext.Parser { private HeaderSettableVCFCodec codec = null; private final List<Allele> alleles; private final String chrom; private final int start; public Parser(List<Allele> alleles, String chrom, int start) { this.alleles = alleles; this.chrom = chrom; this.start = start; } @Override public void setHeaderDataCache( LazyParsingGenotypesContext.HeaderDataCache data) { codec = (HeaderSettableVCFCodec)((HeaderDataCache)data).getCodec(); } @Override public LazyGenotypesContext.LazyData parse(final Object data) { if (codec == null || !codec.hasHeader()) throw new IllegalStateException( "Cannot decode genotypes without a codec with a VCFHeader"); final String str; try { str = new String((byte[])data, "UTF-8"); } catch (UnsupportedEncodingException absurd) { throw new RuntimeException( "Can never happen on a compliant Java implementation because "+ "UTF-8 is guaranteed to be supported"); } return codec.createGenotypeMap(str, alleles, chrom, start); } } } // This is a HACK. But, the functionality is only in AbstractVCFCodec so it // can't be helped. This is preferable to copying the functionality into // parse() above. class HeaderSettableVCFCodec extends AbstractVCFCodec { public boolean hasHeader() { return header != null; } public void setHeaderAndVersion(VCFHeader header, VCFHeaderVersion ver) { this.header = header; this.version = ver; } @Override public Object readActualHeader(LineIterator reader) { throw new UnsupportedOperationException( "Internal error: this shouldn't be called"); } @Override public List<String> parseFilters(String filterString) { throw new UnsupportedOperationException( "Internal error: this shouldn't be called"); } @Override public boolean canDecode(String s) { return true; } }