gt: 		if (rgIdx == null)
context: package net.malariagen.gatk.walker;
  
  import java.lang.reflect.Constructor;
  import java.lang.reflect.InvocationTargetException;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  import net.sf.samtools.AlignmentBlock;
  import net.sf.samtools.SAMReadGroupRecord;
  import net.sf.samtools.SAMRecord;
  
  import org.broadinstitute.sting.utils.sam.GATKSAMRecord;
  
  public abstract class FragmentLengths {
  
  	public interface Listener {
  		public void fragmentFound(String chrom, String sample, String readGroup, int start, int end);
  	}
  
  	public class FirstMate {
  		int start;
  		int stop;
  		int length;
  		int trim;
  	}
  
  	protected long size;
  
  	protected int maxLength;
  	protected Collection<String> samples;
  	protected Collection<String> readGroups;
  	protected Map<String, Integer> rgIndex;
  	protected Map<String, Integer> smIndex;
  	protected Map<String, FirstMate> firstMates = new HashMap<String, FirstMate>(
  			100);
  
  	Set<Listener> listeners = new HashSet<Listener>();
  	
  	public static long FREQ_SIZE_THR = 1000;
  
  	protected int minimumMappingQuality = 0; 
  
  	public static FragmentLengths create(Collection<String> samples,
  			Collection<String> rgs, int maxLength, int minimumMappingQuality) {
  		return new FragmentLengthArrays(samples, rgs, maxLength, minimumMappingQuality);
  	}
  	
  	public static FragmentLengths create(Collection<String> samples,
  			Collection<String> rgs, int maxLength, Class<? extends FragmentLengths> clazz) {
  		if (!FragmentLengths.class.isAssignableFrom(clazz))
  			throw new IllegalArgumentException("not a fl class");
  		Constructor<? extends FragmentLengths> c;
  		try {
  			c = clazz.getConstructor(Collection.class, Collection.class, Integer.TYPE);
  		} catch (NoSuchMethodException e) {
  			throw new UnsupportedOperationException("no suitable constructor found in " + clazz.getName(),e);
  		} catch (SecurityException e) {
  			throw new UnsupportedOperationException("no suitable constructor found in " + clazz.getName(),e);
  		}
  		if (c == null)
  			throw new UnsupportedOperationException("no suitable constructor found in " + clazz.getName());
  		FragmentLengths result;
  		try {
  			result = c.newInstance(samples,rgs,maxLength);
  		} catch (InstantiationException e) {
  			throw new UnsupportedOperationException("no suitable constructor found in " + clazz.getName(),e);
  		} catch (IllegalAccessException e) {
  			throw new UnsupportedOperationException("no suitable constructor found in " + clazz.getName(),e);
  		} catch (IllegalArgumentException e) {
  			throw new UnsupportedOperationException("no suitable constructor found in " + clazz.getName(),e);
  		} catch (InvocationTargetException e) {
  			throw new UnsupportedOperationException("no suitable constructor found in " + clazz.getName(),e);
  		}
  		return result;
  	}
  	
  
  	public static FragmentLengths merge(FragmentLengths fl1, FragmentLengths fl2) {
  		long newSize = fl1.size + fl2.size;
  
  		if (newSize > FREQ_SIZE_THR
  				&& !(fl1 instanceof FragmentLengthFrequencies)) {
  			FragmentLengthFrequencies result = new FragmentLengthFrequencies(
  					fl1.samples, fl1.readGroups, fl1.maxLength, fl1.minimumMappingQuality);
  			result.mergeIn(fl1);
  			result.mergeIn(fl2);
  			result.listeners.addAll(fl1.listeners);
  			result.listeners.addAll(fl2.listeners);
  			return result;
  		} else if (fl1.getClass().equals(fl2.getClass())) {
  			fl1.mergeIn(fl2);
  			fl1.listeners.addAll(fl2.listeners);
  			return fl1;
  		} else if (fl1 instanceof FragmentLengthFrequencies) {
  			fl1.mergeIn(fl2);
  			fl1.listeners.addAll(fl2.listeners);
  			return fl1;
  		} else {
  			FragmentLengthFrequencies result = new FragmentLengthFrequencies(
  					fl1.samples, fl1.readGroups, fl1.maxLength, fl1.minimumMappingQuality);
  			result.mergeIn(fl1);
  			result.mergeIn(fl2);
  			result.listeners.addAll(fl1.listeners);
  			result.listeners.addAll(fl2.listeners);
  			return result;
  		}
  	}
  	
  	protected FragmentLengths(Collection<String> samples,
  			Collection<String> rgs, int maxLength, int minimumMappingQuality) {
  		if (maxLength <= 0)
  			throw new IllegalArgumentException(
  					"max-fragment length must be more than 0");
  		this.maxLength = maxLength;
  		this.minimumMappingQuality = minimumMappingQuality;
  		this.samples = samples;
  		this.readGroups = rgs;
  		int nextSmIdx = 0;
  		int nextRgIdx = 0;
  		smIndex = new HashMap<String, Integer>(samples.size());
  		rgIndex = new HashMap<String, Integer>(rgs.size());
  		for (String s : samples)
  			smIndex.put(s, nextSmIdx++);
  		for (String rg : rgs)
  			rgIndex.put(rg, nextRgIdx++);
  		firstMates = new HashMap<String, FirstMate>(100);
  
  	}
  
  	public boolean add(SAMRecord read) {
  		if (read == null)
  			throw new IllegalArgumentException("input read cannot be null");
  		FirstMate fm =  firstMates.remove(read.getReadName());;
  		if (fm != null)
  			return countSecond(read,fm);
  		else
  			return countFirst(read);
  	}
  
  	private boolean countFirst(SAMRecord read) {
  		if (read.getReadUnmappedFlag())
  			return false;
  		if (read.getMateUnmappedFlag())
  			return false;
  		if (read.getMappingQuality() < minimumMappingQuality)
  			return false;
  		String mateRef = read.getMateReferenceName();
  		if (!mateRef.equals("=") && !mateRef.equals(read.getReferenceName()))
  			return false;
  		int mateStart = read.getMateAlignmentStart();
  		int start = read.getAlignmentStart();
  		if (mateStart - start > maxLength || start - mateStart > maxLength)
  			return false;
  		if (read.getReadNegativeStrandFlag())
  			return false;
  		FirstMate fm = new FirstMate();
  		fm.length = read.getReadLength();
  		fm.start = read.getAlignmentStart();
  		fm.stop = read.getAlignmentEnd();
  		fm.trim = (fm.stop - fm.start + 1 == fm.length) ? 0
  				: calculateTrim(read);
  		firstMates.put(read.getReadName(), fm);
  		return false;
  	}
  
  	private int calculateTrim(SAMRecord read) {
  		List<AlignmentBlock> blocks = read.getAlignmentBlocks();
  		int lastPos = 0;
  		int result = 0;
  		for (AlignmentBlock b : blocks) {
  			result += b.getReadStart() - lastPos - 1;
  			lastPos = b.getReadStart() + b.getLength() - 1;
  		}
  		result += read.getReadLength() - lastPos - 1;
  		return result;
  	}
  
  	protected boolean countSecond(SAMRecord read, FirstMate fm) {
  		if (!read.getReadNegativeStrandFlag())
  			return false;
  		if (read.getMappingQuality() < minimumMappingQuality)
  			return false;
  		String chrom = read.getReferenceName();
  		int start = read.getAlignmentStart();
  		int end = read.getAlignmentEnd();
  		int length = read.getReadLength();
  		int trim = ((end - start + 1 == length) ? 0 : calculateTrim(read));
  		int fragmentLength = end - fm.start + 1 + fm.trim + trim;
  		int insertLength = fragmentLength - length - fm.length;
  		SAMReadGroupRecord rg = read.getReadGroup();
  		if (rg == null)
  			throw new IllegalArgumentException(
  					"reads need to belong to a read-group");
  		Integer smIdx = smIndex.get(rg.getSample());
  		Integer rgIdx = rgIndex.get(rg.getId());
  		if (smIdx == null)
  			return false;
  