/* EnsemblCorbaSequence.java
 *
 * created: Mon Feb  8 1999
 *
 * This file is part of Artemis
 * 
 * Copyright (C) 1998,1999,2000  Genome Research Limited
 * 
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /nfs/disk222/yeastpub/Repository/powmap/uk/ac/sanger/pathogens/embl/EnsemblCorbaSequence.java,v 1.6 2000/04/17 14:30:30 kmr Exp $
 **/

package uk.ac.sanger.pathogens.embl;

import java.io.IOException;

/**
 *  This is an implementation of the Sequence interface that can read itself
 *  from an EnsEMBL Corba object.
 *
 *  @author Kim Rutherford
 *  @version $Id: EnsemblCorbaSequence.java,v 1.6 2000/04/17 14:30:30 kmr Exp $
 **/

public class EnsemblCorbaSequence implements Sequence {
  /**
   *  Create a new EnsemblCorbaSequence object from the given handle.
   *  @param data This is the corba object that we will read from.
   **/
  public EnsemblCorbaSequence (final Ensembl.artemis.BioSequence seq_handle) {
    this.seq_handle = seq_handle;

    final StringBuffer buffer = new StringBuffer ();

    final int max_request_size = seq_handle.max_sequence_request ();

    final int sequence_length = seq_handle.length ();

    for (int i = 0 ; i < sequence_length ; i += max_request_size) {
      int last_base_of_chunk = (i + 1) * max_request_size;

      if (last_base_of_chunk > sequence_length) {
        last_base_of_chunk = sequence_length;
      }

      final int first_base_of_chunk = i * max_request_size + 1;
      
      try {
        final String sequence_chunk =
          seq_handle.getSubSequence (first_base_of_chunk, last_base_of_chunk);

        buffer.append (sequence_chunk);
      } catch (Ensembl.artemis.RequestedSequenceTooLong e) {
        throw new Error ("internal error - unexpected exception: " + e);
      }
    }

    sequence = buffer.toString ();
    
    for (int i = 0 ; i < length () ; ++i) {
      switch (sequence.charAt (i)) {
      case 'a':
      case 'A':
        ++a_count;
        break;
      case 'c':
      case 'C':
        ++c_count;
        break;
      case 't':
      case 'T':
        ++t_count;
        break;
      case 'g':
      case 'G':
        ++g_count;
        break;
      default:
        break;
      }
    }
  }

  /**
   *  Return an identifier for this sequence.  This will most likely be a
   *  discription (eg. from a FASTA header).  Returns null if there is no
   *  identifier for the sequence.
   **/
  public String getIdentifier () {
    return null;
  }

  /**
   *  Return this Sequence as a String.
   **/
  public String toString () {
    return sequence;
  }

  /**
   *  Return a the given range of bases as a String.
   *  @param start The start base of the range.
   *  @param end The end base of the range.
   **/
  public String getSubSequence (int start, int end) {
    if (start == 1 && end == length ()) {
      return sequence;
    }

    // sanity checks
    if (end > length ()) {
      end = length ();
    }

    if (start < 1) {
      start = 1;
    }

    if (end < start) {
      // empty range
      return "";
    } else {
      return sequence.substring (start - 1, end);
    }
  }

  /**
   *  Set this sequence to hold the bases in the given String - does nothing
   *  for EnsemblCorbaSequence objects.
   **/
  public void setFromString (final String new_sequence) {
    // just do nothing
  }

  /**
   *  Returns the length of the sequence in bases.
   **/
  public int length () {
    return sequence.length ();
  }

  /**
   *  Return the count of c bases in the whole sequence.
   **/
  public int getCCount () {
    return c_count;
  }

  /**
   *  Return the count of g bases in the whole sequence.
   **/
  public int getGCount () {
    return g_count;
  };

  /**
   *  Return the count of a bases in the whole sequence.
   **/
  public int getACount () {
    return a_count;
  };

  /**
   *  Return the count of t bases in the whole sequence.
   **/
  public int getTCount () {
    return t_count;
  }

  /**
   *  Return the count of non-g,c,t,a bases in the whole sequence.
   **/
  public int getOtherCount () {
    return
      length () - (getCCount () + getACount () + getTCount () + getGCount ());
  }

  /**
   *  The sequence that was read from the Corba object by the constructor.
   **/
  private String sequence;
  
  /**
   *  The corba object that was passed to the constructor.
   **/
  private Ensembl.artemis.BioSequence seq_handle;

  /**
   *  Count of the occurrences of C bases in the sequence set by the
   *  constructor.
   **/
  private int c_count = 0;

  /**
   *  Count of the occurrences of T bases in the sequence set by the
   *  constructor.
   **/
  private int t_count = 0;

  /**
   *  Count of the occurrences of A bases in the sequence set by the
   *  constructor.
   **/
  private int a_count = 0;

  /**
   *  Count of the occurrences of G bases in the sequence set by the
   *  constructor.
   **/
  private int g_count = 0;
}


