/*
* Eoulsan development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public License version 2.1 or
* later and CeCILL-C. This should be distributed with the code.
* If you do not have a copy, see:
*
* http://www.gnu.org/licenses/lgpl-2.1.txt
* http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt
*
* Copyright for this code is held jointly by the Genomic platform
* of the Institut de Biologie de l'École normale supérieure and
* the individual authors. These should be listed in @author doc
* comments.
*
* For more information on the Eoulsan project and its aims,
* or to join the Eoulsan Google group, visit the home page
* at:
*
* http://outils.genomique.biologie.ens.fr/eoulsan
*
*/
package fr.ens.biologie.genomique.eoulsan.bio.alignmentsfilters;
import htsjdk.samtools.SAMRecord;
import java.util.ArrayList;
import java.util.List;
/**
* This class define a buffer that store all the alignments with the same read
* name before to apply an alignment filter. This class only works with
* alignment data where all the alignments for a read name are in straight.
* @since 1.1
* @author Laurent Jourdren
* @author Claire Wallon
*/
public class ReadAlignmentsFilterBuffer {
private final ReadAlignmentsFilter filter;
private final List<SAMRecord> list = new ArrayList<>();
private String currentName;
private final boolean reuseResultList;
/**
* Add the provided alignment to a list of SAMRecord objects if this alignment
* has the same read name as the other alignments of the list.
* @param alignment SAM alignment
* @return true if the alignment provides is stored, i.e. if it has the same
* read name as the other alignments already stored.
*/
public boolean addAlignment(final SAMRecord alignment) {
if (alignment == null) {
return false;
}
final String name = parseAlignmentName(alignment);
// The previous list of alignments has been already treated
if (this.currentName == null) {
this.currentName = name;
}
// The previous list of alignments is not already treated
else {
// The current alignment has a new read name
if (!this.currentName.equals(name)) {
this.currentName = null;
return false;
}
}
// The read name is equal to the previous
// (so the alignment is in the same multiple alignment than the
// previous one)
this.list.add(alignment);
return true;
}
/**
* Get the list of the alignments that pass the tests of the filter with the
* same read name. Warning if reuseResultList argument in the constructor is
* set to true, this method will always returns the same object.
* @return a list of SAM record
*/
public List<SAMRecord> getFilteredAlignments() {
// Filter alignment
this.filter.filterReadAlignments(this.list);
// Return the list of filtered alignment
if (this.reuseResultList) {
return this.list;
}
List<SAMRecord> results = new ArrayList<>(this.list);
this.list.clear();
this.currentName = null;
return results;
}
/**
* Parse alignment name.
* @param alignment the alignment
* @return the name of the sequence in the alignment
*/
private static String parseAlignmentName(final SAMRecord alignment) {
final String alignmentName = alignment.getReadName();
final int spaceIndex = alignmentName.indexOf(' ');
if (spaceIndex == -1) {
return alignmentName;
}
return alignmentName.substring(0, spaceIndex);
}
//
// Constructor
//
/**
* Public constructor.
* @param filter the filter to use with this buffer.
*/
public ReadAlignmentsFilterBuffer(final ReadAlignmentsFilter filter) {
this(filter, false);
}
/**
* Public constructor.
* @param filter the filter to use with this buffer
* @param reuseResultList true if the getFilteredAlignments() method must
* return always the same internal list
*/
public ReadAlignmentsFilterBuffer(final ReadAlignmentsFilter filter,
final boolean reuseResultList) {
if (filter == null) {
throw new NullPointerException("The alignment filter is null");
}
this.filter = filter;
this.reuseResultList = reuseResultList;
}
}