/*
 * Copyright 2009 Lari Natri <lari.natri@gmail.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package compid.sequences;


/**
 * This is an abstract base class for sequence aligners.
 * @author Lari Natri
 */
public abstract class Aligner
{

    /** Holds the similarity matrix used by this aligner. Can be used from
    within inherited classes. */
    protected final SimilarityMatrix simMatrix;
    
    /**
     * This constructor must be called from inherited classes' constructors
     * @param s SimilarityMatrix used by this aligner
     * @throws java.lang.NullPointerException thrown if s==null
     */
    protected Aligner(SimilarityMatrix s) throws NullPointerException
    {
        if (s == null) {
            throw new NullPointerException();
        }
        simMatrix = s;
    }

    /**
     * Checks if parameter sequence can be used with this aligner aka is
     * compatible with the set SimilarityMatrix. Calls SimilarityMatrix's
     * isCompatible(Sequence) method.
     * @param seq Sequence to check
     * @return true if compatible, false otherwise
     */
    public final boolean isCompatible(Sequence seq)
    {
        return simMatrix.isCompatible(seq);
    }

    /**
     * Returns the similarity matrix used by this aligner.
     * @return similarity matrix
     */
    public final SimilarityMatrix getSimilarityMatrix()
    {
        return simMatrix;
    }

    /*
    protected final Sequence[] getRandomizedSequences(Sequence seq, int n) {
        if (n<1) throw new IllegalArgumentException();

        final Sequence[] result = new Sequence[n];
        for (int i=0; i<n; ++i) {
            result[i] = seq.componentsInRandomOrder();
        }
        return result;
    }
    */

    /**
     * Does the alignment. Calls an abstract method implemented in derived
     * classes to do the actual alignment.
     * @param seqA first sequence
     * @param seqB second sequence
     * @return alignment
     * @throws java.lang.Exception thrown if any problem occurred in aligning,
     *         including 'sequences incompatible with similarity matrix'
     */
    public final Alignment align(Sequence seqA, Sequence seqB) throws Exception
    {
        if (this.isCompatible(seqA) && this.isCompatible(seqB)) {
            return this.doActualAlignment(seqA, seqB);
        } else {
            throw new Exception("Sequences not compatible");
        }
    }

    /**
     * Does the actual alignment. Must be implemented in derived classes.
     * @param seqA first sequence
     * @param seqB second sequence
     * @return alignment
     * @throws java.lang.Exception thrown if any problem occurred in aligning
     */
    protected abstract Alignment doActualAlignment(Sequence seqA, Sequence seqB)
            throws Exception;
    
    
}
