// Path: src/main/java/org/seqdoop/hadoop_bam/FormatConstants.java
// public enum BaseQualityEncoding { Illumina, Sanger };
// 
// Path: src/main/java/org/seqdoop/hadoop_bam/util/ConfHelper.java
// public class ConfHelper
// {
// 	/**
// 	 * Convert a string to a boolean.
// 	 *
// 	 * Accepted values: "yes", "true", "t", "y", "1"
// 	 *                  "no", "false", "f", "n", "0" 
// 	 * All comparisons are case insensitive.
// 	 *
// 	 * If the value provided is null, defaultValue is returned.
// 	 *
// 	 * @exception IllegalArgumentException Thrown if value is not
// 	 * null and doesn't match any of the accepted strings.
// 	 */
// 	public static boolean parseBoolean(String value, boolean defaultValue)
// 	{
// 		if (value == null)
// 			return defaultValue;
// 
// 		value = value.trim();
// 
// 		// any of the following will 
// 		final String[] acceptedTrue = new String[]{ "yes", "true", "t", "y", "1" };
// 		final String[] acceptedFalse = new String[]{ "no", "false", "f", "n", "0" };
// 
// 		for (String possible: acceptedTrue)
// 		{
// 			if (possible.equalsIgnoreCase(value))
// 				return true;
// 		}
// 		for (String possible: acceptedFalse)
// 		{
// 			if (possible.equalsIgnoreCase(value))
// 				return false;
// 		}
// 
// 		throw new IllegalArgumentException("Unrecognized boolean value '" + value + "'");
// 	}
// 
// 	public static boolean parseBoolean(Configuration conf, String propertyName, boolean defaultValue)
// 	{
// 		return parseBoolean(conf.get(propertyName), defaultValue);
// 	}
// }


import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.compress.CompressionCodec;
import org.apache.hadoop.io.compress.CompressionCodecFactory;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.JobContext;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.seqdoop.hadoop_bam.FormatConstants.BaseQualityEncoding;
import org.seqdoop.hadoop_bam.util.ConfHelper;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.CharacterCodingException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
// Copyright (C) 2011-2012 CRS4.
//
// This file is part of Hadoop-BAM.
//
// 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;




/**
 * Reads the Illumina qseq sequence format.
 * Key: instrument, run number, lane, tile, xpos, ypos, read number, delimited by ':' characters.
 * Value:  a SequencedFragment object representing the entry.
 */
public class QseqInputFormat extends FileInputFormat<Text,SequencedFragment>
{
	public static final String CONF_BASE_QUALITY_ENCODING = "hbam.qseq-input.base-quality-encoding";
	public static final String CONF_FILTER_FAILED_QC      = "hbam.qseq-input.filter-failed-qc";
	public static final String CONF_BASE_QUALITY_ENCODING_DEFAULT = "illumina";

	public static class QseqRecordReader extends RecordReader<Text,SequencedFragment>
	{
		/*
		 * qseq format:
		 * 11 tab-separated columns
		 *
		 * 1) Instrument
		 * 2) Run id
		 * 3) Lane number
		 * 4) Tile number
		 * 5) X pos
		 * 6) Y pos
		 * 7) Index sequence (0 for runs without multiplexing)
		 * 8) Read Number
		 * 9) Base Sequence
		 * 10) Base Quality
		 * 11) Filter: did the read pass filtering? 0 - No, 1 - Yes.
		 */
		// start:  first valid data index
		private long start;
		// end:  first index value beyond the slice, i.e. slice is in range [start,end)
		private long end;
		// pos: current position in file
		private long pos;
		// file:  the file being read
		private Path file;

		private LineReader lineReader;
		private InputStream inputStream;
		private Text currentKey = new Text();
		private SequencedFragment currentValue = new SequencedFragment();

		private Text buffer = new Text();
		private static final int NUM_QSEQ_COLS = 11;
		// for these, we have one per qseq field
		private int[] fieldPositions = new int[NUM_QSEQ_COLS];
		private int[] fieldLengths = new int[NUM_QSEQ_COLS];

// Path: src/main/java/org/seqdoop/hadoop_bam/FormatConstants.java
// public enum BaseQualityEncoding { Illumina, Sanger };
// 
// Path: src/main/java/org/seqdoop/hadoop_bam/util/ConfHelper.java
// public class ConfHelper
// {
// 	/**
// 	 * Convert a string to a boolean.
// 	 *
// 	 * Accepted values: "yes", "true", "t", "y", "1"
// 	 *                  "no", "false", "f", "n", "0" 
// 	 * All comparisons are case insensitive.
// 	 *
// 	 * If the value provided is null, defaultValue is returned.
// 	 *
// 	 * @exception IllegalArgumentException Thrown if value is not
// 	 * null and doesn't match any of the accepted strings.
// 	 */
// 	public static boolean parseBoolean(String value, boolean defaultValue)
// 	{
// 		if (value == null)
// 			return defaultValue;
// 
// 		value = value.trim();
// 
// 		// any of the following will 
// 		final String[] acceptedTrue = new String[]{ "yes", "true", "t", "y", "1" };
// 		final String[] acceptedFalse = new String[]{ "no", "false", "f", "n", "0" };
// 
// 		for (String possible: acceptedTrue)
// 		{
// 			if (possible.equalsIgnoreCase(value))
// 				return true;
// 		}
// 		for (String possible: acceptedFalse)
// 		{
// 			if (possible.equalsIgnoreCase(value))
// 				return false;
// 		}
// 
// 		throw new IllegalArgumentException("Unrecognized boolean value '" + value + "'");
// 	}
// 
// 	public static boolean parseBoolean(Configuration conf, String propertyName, boolean defaultValue)
// 	{
// 		return parseBoolean(conf.get(propertyName), defaultValue);
// 	}
// }


// Path: src/main/java/org/seqdoop/hadoop_bam/QseqInputFormat.java
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.compress.CompressionCodec;
import org.apache.hadoop.io.compress.CompressionCodecFactory;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.JobContext;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.seqdoop.hadoop_bam.FormatConstants.BaseQualityEncoding;
import org.seqdoop.hadoop_bam.util.ConfHelper;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.CharacterCodingException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

// Copyright (C) 2011-2012 CRS4.
//
// This file is part of Hadoop-BAM.
//
// 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;




/**
 * Reads the Illumina qseq sequence format.
 * Key: instrument, run number, lane, tile, xpos, ypos, read number, delimited by ':' characters.
 * Value:  a SequencedFragment object representing the entry.
 */
public class QseqInputFormat extends FileInputFormat<Text,SequencedFragment>
{
	public static final String CONF_BASE_QUALITY_ENCODING = "hbam.qseq-input.base-quality-encoding";
	public static final String CONF_FILTER_FAILED_QC      = "hbam.qseq-input.filter-failed-qc";
	public static final String CONF_BASE_QUALITY_ENCODING_DEFAULT = "illumina";

	public static class QseqRecordReader extends RecordReader<Text,SequencedFragment>
	{
		/*
		 * qseq format:
		 * 11 tab-separated columns
		 *
		 * 1) Instrument
		 * 2) Run id
		 * 3) Lane number
		 * 4) Tile number
		 * 5) X pos
		 * 6) Y pos
		 * 7) Index sequence (0 for runs without multiplexing)
		 * 8) Read Number
		 * 9) Base Sequence
		 * 10) Base Quality
		 * 11) Filter: did the read pass filtering? 0 - No, 1 - Yes.
		 */
		// start:  first valid data index
		private long start;
		// end:  first index value beyond the slice, i.e. slice is in range [start,end)
		private long end;
		// pos: current position in file
		private long pos;
		// file:  the file being read
		private Path file;

		private LineReader lineReader;
		private InputStream inputStream;
		private Text currentKey = new Text();
		private SequencedFragment currentValue = new SequencedFragment();

		private Text buffer = new Text();
		private static final int NUM_QSEQ_COLS = 11;
		// for these, we have one per qseq field
		private int[] fieldPositions = new int[NUM_QSEQ_COLS];
		private int[] fieldLengths = new int[NUM_QSEQ_COLS];

		private BaseQualityEncoding qualityEncoding;