/*
 *This library is free software; you can redistribute it and/or
 *modify it under the terms of the GNU Lesser General Public
 *License as published by the Free Software Foundation; either
 *version 2.1 of the License, or (at your option) any later version.
 *
 *This library 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
 *Lesser General Public License for more details.
 *
 *You should have received a copy of the GNU Lesser General Public
 *License along with this library; if not, write to the Free Software
 *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* 
 * This software was written by Phillip Lord (p.lord@hgmp.mrc.ac.uk)
 * whilst at the University of Manchester as a Pfizer post-doctoral 
 * Research Fellow. 
 *
 * The initial code base is copyright by Pfizer, or the University
 * of Manchester. Modifications to the initial code base are copyright
 * of their respective authors, or their employers as appropriate. 
 * Authorship of the modifications may be determined from the ChangeLog
 * placed at the end of this file
 */

package uk.ac.man.bioinf.sequence.complex; // Package name inserted by JPack
import uk.ac.man.bioinf.sequence.AbstractMutableSequence;
import uk.ac.man.bioinf.sequence.Element;
import uk.ac.man.bioinf.sequence.InvalidSequenceTypeException;
import uk.ac.man.bioinf.sequence.complex.ComplexSequenceType;
import uk.ac.man.bioinf.sequence.event.SequenceEventType;
import uk.ac.man.bioinf.sequence.event.SequenceVetoException;
import uk.ac.man.bioinf.sequence.event.VetoableSequenceEvent;


/**
 * AbstractComplexSequence.java
 *
 *
 * Created: Fri Nov 24 13:33:32 2000
 *
 * @author Phillip Lord
 * @version $Id: AbstractComplexSequence.java,v 1.2 2001/04/11 17:04:43 lord Exp $
 */

public abstract class AbstractComplexSequence extends AbstractMutableSequence implements ComplexSequence
{
  private ComplexSequenceType type;

  public AbstractComplexSequence( ComplexSequenceType type )
  {
    super( type );
    this.type = type;
  }
  
  public ComplexSequenceType getComplexType()
  {
    return type;
  }
  
  protected void checkSequenceType( Element[] element ) throws InvalidSequenceTypeException
  {
    for( int i = 0; i < element.length; i++ ){
      checkSequenceType( element[ i ] );
    }
  }
  
  protected void checkSequenceType( Element element ) throws InvalidSequenceTypeException
  {
    if( !(element instanceof ComplexElement) ){
      super.checkSequenceType( element );
    }
    else{
      checkComplexSequenceType( (ComplexElement)element );
    }
  }
  
  protected void checkComplexSequenceType( ComplexElement[] element ) throws InvalidSequenceTypeException
  {
    for( int i = 0; i < element.length; i++ ){
      checkComplexSequenceType( element[ i ] );
    }
  }
  
  protected void checkComplexSequenceType( ComplexElement element ) throws InvalidSequenceTypeException
  {
    if( !type.isAllowableElement( element ) ){
      throw getComplexSequenceTypeException( element );
    }
  }
  
  protected InvalidSequenceTypeException getComplexSequenceTypeException( Element element )
  {
    return new InvalidSequenceTypeException
      ( "Element " + element + " is not a valid part of the complex sequence type " + 
	type.toString() );
  }
  
  public ComplexElement addModificationAt( Modification mod, int index ) throws SequenceVetoException
  {
    ComplexElement elem = getComplexElementAt( index );
    ComplexElement newElem = ComplexElementFactory.addComplexElement
      ( elem, mod );
    
    VetoableSequenceEvent event = new VetoableSequenceEvent
      ( this, index, SequenceEventType.SET );
    
    fireVetoableSequenceEvent( event );
    setElementAtQuietly( newElem, index );
    fireSequenceEvent( event );
  
    return newElem;
  }
  
  protected abstract ComplexElement setElementAtQuietly( ComplexElement element, int index );

  public ComplexElement removeModificationAt( Modification mod, int index ) throws SequenceVetoException
  {
    ComplexElement elem = getComplexElementAt( index );
    ComplexElement newElem = ComplexElementFactory.removeComplexElement
      ( elem, mod );
    
    VetoableSequenceEvent event = new VetoableSequenceEvent
      ( this, index, SequenceEventType.SET );
    
    fireVetoableSequenceEvent( event );
    setElementAtQuietly( newElem, index );
    fireSequenceEvent( event );
  
    return newElem;
  }

  public char[] getComplexElementAtAsChar( int index )
  {
    ComplexElement elem = getComplexElementAt( index );
    Modification[] mods = elem.getModifications();
    
    char[] chars = new char[ mods.length + 2 ];
    
    chars[ 0 ] = elem.toChar();
    
    for( int i = 0; i < mods.length; i++ ){
      chars[ i + 1 ] = mods[ i ].toChar();
    }
    chars[ chars.length - 1 ] = '_';

    return chars;    
  }
  
  public char[] getComplexSequenceAsChars()
  {
    // we don't know how long this is going to be before we do it. 
    StringBuffer buf = new StringBuffer();
    for( int i = 0; i < getLength(); i++ ){
      buf.append( getComplexElementAtAsChar( i + 1 ) );
    }
    
    return buf.toString().toCharArray();
  }
} // AbstractComplexSequence



/*
 * ChangeLog
 * $Log: AbstractComplexSequence.java,v $
 * Revision 1.2  2001/04/11 17:04:43  lord
 * Added License agreements to all code
 *
 * Revision 1.1  2000/11/27 18:14:02  lord
 * Realised that I had not implemented the ComplexSequence. Have now done
 * this and have made quite a few changes to this package as a result
 *
 */

