package STRAL::SequenceElement;

use strict;
use vars qw($VERSION);
use Carp;

$VERSION = '0.01';

# POD-formatted documentation
#-------------------------------------------------------------------------------

=head1 NAME

STRAL::SequenceElement - Object representation of an amino acid residue 

=head1 SYNOPSIS

  use STRAL::SequenceElement;

  my $element = STRAL::SequenceElement->new(
    {
      "ordinal" => $elementOrdinal,
      "name" => $elementName,
      "residue" => $elementResidue 
    });

  $ordinal = $element->getOrdinal();
  $name = $element->getName();
  $residue = $element->getResidue();
  $chainGuess = $element->getChainFromName();
  $newElement = $element->clone();

=head1 EXAMPLES

  use STRAL::SequenceElement;

  my $element = STRAL::SequenceElement->new(
    {
      "ordinal" => $elementOrdinal,
      "name" => $elementName,
      "residue" => $elementResidue 
    });

  $ordinal = $element->getOrdinal();
  $name = $element->getName();
  $residue = $element->getResidue();
  $chainGuess = $element->getChainFromName();
  $newElement = $element->clone();

=head1 DESCRIPTION

SequenceElement is the object representation of an amino acid residue.

If you are using SequenceElement, you should probably try to use a source
(such as GenericAlignment::AlignmentSource - only one implemented for now)
to create an element, rather than build one yourself.

=head1 APPENDIX

The following documentation describes the functions in this package

=cut

#-------------------------------------------------------------------------------

=head2 new

 Usage     : $element = STRAL::SequenceElement->new(
               {
                 "ordinal" => $elementOrdinal,
                 "name" => $elementName,
                 "residue" => $elementResidue 
               });
 Function  : Creates a new STRAL::SequenceElement object
 Arguments : HashRef - name and value pairs for all accepted parameters,
                       which include:
               name - name for this residue (ie "10", "10_A", or "10B_A")
	       ordinal - unique number that is this residues position
	       residue - amino acid code for the residue
	                 (code and name may be kept track of in the future) 
 Example   : See Usage
 Returns   : A new STRAL::SequenceElement object

=cut

sub new
{
  my ($classType, $paramHashRef) = @_;

  # Check for completeness of parameters
  if(! defined $paramHashRef ||
     ref($paramHashRef) ne "HASH")
  {
    confess("first parameter to STRAL::SequenceElement " .
            "must be a hash-ref to initialization parameters");
  }

  # Check for required elements
  if(! exists $paramHashRef->{"residue"})
  {
    confess("required parameter \"residue\" must be present");
  }
  if(! exists $paramHashRef->{"ordinal"})
  {
    confess("required parameter \"ordinal\" must be present");
  }
  if(! exists $paramHashRef->{"name"})
  {
    confess("required parameter \"name\" must be present");
  }

  my $this = {};
  bless($this, $classType);

  $this->{"d_residue"} = $paramHashRef->{"residue"};
  $this->{"d_ordinal"} = $paramHashRef->{"ordinal"};
  $this->{"d_name"} = $paramHashRef->{"name"};

  return $this;
}

#-------------------------------------------------------------------------------

=head2 getOrdinal 

 Usage     : $ordinal = $element->getOrdinal(); 
 Function  : Gets the ordinal for this element
 Arguments : <n/a> 
 Example   : See Usage
 Returns   : Integer - ordinal for this element

=cut

sub getOrdinal
{
  my ($this) = @_;

  return $this->{"d_ordinal"};
}

#-------------------------------------------------------------------------------

=head2 getName 

 Usage     : $name = $element->getName();
 Function  : Gets the name for this element
 Arguments : <n/a> 
 Example   : See Usage
 Returns   : String - name for this element

=cut

sub getName
{
  my ($this) = @_;

  return $this->{"d_name"};
}

#-------------------------------------------------------------------------------

=head2 getResidue 

 Usage     : $residue = $element->getResidue();
 Function  : Gets the residue for this element 
 Arguments : <n/a> 
 Example   : See Usage
 Returns   : String - residue for this element 

=cut

sub getResidue
{
  my ($this) = @_;

  return $this->{"d_residue"};
}

#-------------------------------------------------------------------------------

=head2 getChainFromName 

 Usage     : $chainGuess = $element->getChainFromName();
 Function  : Gets a guess at the chain name for this element.  Anticipated 
             value types "" (empty string) and "A" (or another letter, the 
	     actual chain spec). Examples:
	       Name          Returns
                1_A                A
	       2B_C                B
	          3   (empty string) 
		 4D   (empty string) 
 Arguments : <n/a> 
 Example   : See Usage
 Returns   : String - guess at the chain name for this element

=cut

sub getChainFromName
{
  my ($this) = @_;

  my $currName = $this->{"d_name"};

  if($currName !~ /_.$/)
  {
    # Return blank chain specifier if no underscore in name 
    return "";
  }
  else
  {
    my ($chainSpecifier) = ($currName =~ /_(.)$/);
    return $chainSpecifier;
  }
}

#-------------------------------------------------------------------------------

=head2 clone 

 Usage     : $newElement = $element->clone(); 
 Function  : Creates a copy of this element 
 Arguments : <n/a> 
 Example   : See Usage
 Returns   : STRAL::SequenceElement - a duplicate of this element 

=cut

sub clone
{
  my ($this) = @_;

  return STRAL::SequenceElement->new(
    {
      "residue" => $this->{"d_residue"},
      "ordinal" => $this->{"d_ordinal"},
      "name" => $this->{"d_name"}
    });
}

1; # Got one?

__END__

=head1 AUTHOR

Clinton Torres (clinton.torres@llnl.gov)

=head1 SEE ALSO

=cut