#!/usr/bin/perl
package SeqParamTranslator_base;

##########################################################################
##### Author :	Shuai Weng
##### Date   :  Nov. 2001
##### Description : This object contains methods for 
#####               retrieving dictyBase feature related info for a given 
#####               dictyBaseid, orf name, gene name or an alias name.
#####
##### See documentation for usage details:
#####
##### http:///usr/local/dicty/www_dictybase/db/lib/staff/dictyBase/programmer/SeqParamTranslator.html
#####
#######################################################################
use strict;
use Bio::DB::GenBank;
use Bio::DB::GenPept;

use DBI;

use lib "/usr/local/dicty/www_dictybase/db/lib/common";
use TextUtil qw (DeleteUnwantedChar);
use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase/Objects";
use ConfigPathdictyBase;
use Feature;
use Locus;
use Clone;
use dictyBaseid;
use Alias;

#######################################################################
######################## global variables #############################
our $dbh;
our $GCGDataDir;

#######################################################################
sub new {      ############ constructor ###############################
#######################################################################
       
    my ($type, %args) = @_;

    my $self = {};
    bless $self, $type;

    $dbh = $args{'dbh'};
    if (!$dbh) {
	print "You have to pass a database handle to SeqParamTranslator object";
	return;
    }
    $self->{'_query'} = $args{'query'} || $args{'dictyBaseid'};


    if (!$self->{'_query'}) {
	print "You have to pass a query name or dictyBaseid to SeqParamTranslator object";
	return;
    }
    if ($self->{'_query'} !~ /[\*\%]/i) {
	$self->initInfo;
    }
    else {
	$self->getMatchList;
    }
    return $self;
}

#######################################################################
sub type { $_[0]->{_type} }
sub locusObject { $_[0]->{_locusObject} }
sub featureObject { $_[0]->{_featureObject} }
sub chromosome { $_[0]->{_chromosome} }
sub start_coord { $_[0]->{_start_coord} }
sub stop_coord { $_[0]->{_stop_coord} }
sub genbankSeqNm { $_[0]->{_genbankSeqNm} }
sub genbankSeqObject { $_[0]->{_genbankSeqObject} }
sub length { $_[0]->{_length} }
sub error { $_[0]->{_error} }
sub matchList { $_[0]->{_matchList} }

#######################################################################
sub initInfo {
#######################################################################
    my ($self) = @_;

    $self->_initFilePath;

    if ($self->{'_query'} =~ /^ *([SL][0-9]{7}) *$/) {
	$self->{'_dictyBaseid'} = $1;
	$self->{'_query'} = "";
    }	

    if ($self->{'_dictyBaseid'}) {
	my $dictyBaseid = $self->{'_dictyBaseid'};
	&DeleteUnwantedChar(\$dictyBaseid);
	my $dictyBaseidObj = dictyBaseid->new(dbh=>$dbh,
				  dictyBaseid=>$dictyBaseid);
	if (!$dictyBaseidObj) {
	    $self->{'_error'} = "The dictyBaseID = $dictyBaseid is not found in database.";
	    return;
	}
	$self->{'_locus_no'} = $dictyBaseidObj->locus_no;
	$self->{'_feature_no'} = $dictyBaseidObj->feature_no;
	$self->{'_type'} = 'dictyBaseid';
	if ($self->{'_feature_no'}) {
	    $self->createFeatureObject;
        }
	if ($self->{'_locus_no'}) {
	    $self->createLocusObject;
	}
    }
    elsif ($self->{'_query'}) {

	my $query = $self->{'_query'};
	&DeleteUnwantedChar(\$query);
	if ($query =~ /^[0-9]+$/) { ### it is a clone 
	     my ($chrnum, $beg, $end) 
		= Clone->GetChrBegEnd4clone(dbh=>$dbh,
					    clone=>$query);
	    if (!$chrnum) {
		$self->{'_error'} = "No clones found in dictyBase with the name $query.";
		return;
	    }
	    $self->{'_chromosome'} = $chrnum;
	    $self->{'_start_coord'} = $beg;
	    $self->{'_stop_coord'} = $end;
	    $self->{'_type'} = 'clone';
	}
	else {
	    
	    $self->createFeatureObject($query);
	    if ($self->{'_featureObject'}) { ### feature
		$self->{'_type'} = 'feature';
		return;
	    }
	    $self->createLocusObject($query);
	    if ($self->{'_locusObject'}) { ### locus
		$self->{'_type'} = 'locus';
		return;
	    }
	    my $aliasType = Alias->GetAliasTypeBYaliasNm(dbh=>$dbh,
							 alias_name=>$query);

	    if ($aliasType) {  ### alias

		$self->{'_type'} = 'alias';
		
		$aliasType =~ s/^([^\:]+)\:.+$/$1/;

		my $aliasObj = Alias->new(dbh=>$dbh,
					  alias_name=>$query,
					  alias_type=>$aliasType);

		$self->{'_feature_no'} = $aliasObj->feature_no;

		$self->createFeatureObject;

		if (!$self->{'_feature_no'}) {

		    $self->{'_locus_no'} = $aliasObj->getLocusNoList;
		    
		    if ($self->{'_locus_no'} =~ /^[0-9]+\:/) {
			my @locusNo = split(/:/, $self->{'_locus_no'});
			foreach my $locusNo (@locusNo) {
			    my $locusObj = Locus->new(dbh=>$dbh,
						      locus_no=>$locusNo);
			    if ($locusObj) {
				if ($self->{'_matchList'}) {
				    $self->{'_matchList'} .= ":";
				}
				$self->{'_matchList'} .= $locusObj->locus_name;
			    }
			}
		    }
		    else {
			$self->createLocusObject;
		    }
		}
	    }
	    else { #### Try to see if it is a GenBank entry
	
		$self->searchGenBank($query);

	    }
        }
    }
}


########################################################################
sub createFeatureObject {
########################################################################
    my ($self, $name) = @_;
    my $featObj;
    if ($name || $self->{'_feature_name'}) {
	my $featNm = $name || $self->{'_feature_name'};
	$featObj = Feature->new(dbh=>$dbh,
				feature_name=>$featNm);
    }
    elsif ($self->{'_feature_no'}) {
	$featObj = Feature->new(dbh=>$dbh,
				feature_no=>$self->{'_feature_no'});
    }
    if (!$featObj) {
	return;
    }
    $self->{'_featureObject'} = $featObj;
    if ($featObj->locus_no && !$self->{'_locusObject'}) {
	$self->{'_locus_no'} = $featObj->locus_no;
	$self->createLocusObject;
    }
}

########################################################################
sub createLocusObject {
########################################################################
    my ($self, $name) = @_;
    my $locusObj;
    if ($name || $self->{'_locus_name'}) {
	my $locusNm = $name || $self->{'_locus_name'};
	$locusObj = Locus->new(dbh=>$dbh,
			       locus_name=>$locusNm);
    }
    if ($self->{'_locus_no'}) {
	$locusObj = Locus->new(dbh=>$dbh,
			       locus_no=>$self->{'_locus_no'});
    }
    if (!$locusObj) {
	return;
    }
    $self->{'_locusObject'} = $locusObj;
    if (!$self->{'_featureObject'} && $locusObj->featureNameList &&
	$locusObj->featureNameList !~ /\|/) {
	$self->{'_feature_name'} = $locusObj->featureNameList;
	$self->createFeatureObject;
    }
}

########################################################################
sub getMatchList {
########################################################################
    my ($self) = @_;

    $self->_initFilePath;

    $self->{'_query'} =~ s/\*/\%/g;
    my $sth = $dbh->prepare("
        SELECT feature_name
        FROM   CGM_DDB.feature
        WHERE  upper(feature_name) like ?
        UNION
        SELECT locus_name
        FROM   CGM_DDB.locus
        WHERE  upper(locus_name) like ?
        UNION  
        SELECT alias_name
        FROM   CGM_DDB.alias
        WHERE  upper(alias_name) like ?
    ");
    $sth->execute(uc($self->{'_query'}), uc($self->{'_query'}),
		  uc($self->{'_query'}));
    my $matchList;
    while(my ($name) = $sth->fetchrow()) {
	$matchList .= ":".$name;
    }
    
    $self->{'_query'} =~ s/\%/\*/g;
    

    $matchList .= $self->searchGenBank($self->{'_query'}, 1);

    $matchList =~ s/^\://;
    $self->{'_matchList'} = $matchList;
    if (!$self->{'_matchList'}) {
	$self->{'_error'} = "No sequences were found in dictyBase with the name ".$self->{'_query'}.".";
    }
    
    if ($self->{'_matchList'} !~ /\:/) {
	$self->{'_query'} = $self->{'_matchList'};
	$self->{'_matchList'} = "";
	$self->initInfo;
    }
}

########################################################################
sub searchGenBank {
########################################################################
    my ($self, $query, $wildcard) = @_;

    $query =~ s/^gi:([0-9]+)$/$1/i;

    ##### try DNA database 

    my $gb  = new Bio::DB::GenBank();

    my $seqObj = $gb->get_Stream_by_id($query);

    my @gbSeqNm;

    while ( my $seq = $seqObj->next_seq() ) { 
		    
	 if (!$self->{'_genbankSeqObject'}) { 

	     $self->{'_genbankSeqObject'} = $seq;

	 }
	 push(@gbSeqNm, $seq->display_id);
	  
    }

    if (!@gbSeqNm) {

	##### try protein database

	my $gp = new Bio::DB::GenPept();

	$seqObj = $gp->get_Stream_by_id($query);
	
	while ( my $seq = $seqObj->next_seq() ) { 
		    
	    if (!$self->{'_genbankSeqObject'}) { 

		$self->{'_genbankSeqObject'} = $seq;

	    }
	    push(@gbSeqNm, $seq->display_id);
	  
	}

    }


    if (!@gbSeqNm && !$wildcard) {
		    
	 $self->{'_error'} = "No sequence found in dictyBase with the name $query..";
	 return;
		
    }
    $self->{'_type'} = 'gb';

    if (@gbSeqNm == 1) {
		    
	 $self->{'_genbankSeqNm'} = $gbSeqNm[0];
	
	 if ($wildcard) {  return ":".$gbSeqNm[0]; }

    }
    else {

	 $self->{'_matchList'} = join(':', @gbSeqNm);

	 if ($wildcard) {

	     return ":".$self->{'_matchList'};

	 }

    }
    
}

########################################################################
sub _initFilePath {
########################################################################
    my ($self) = @_;
    my $configPath = ConfigPathdictyBase->new;
    $GCGDataDir = $configPath->GCGDataDir;
}

########################################################################
1;
########################################################################

=pod

=head1 Name

SeqParamTranslator.pm    

=head1 Description

This perl object (SeqParamTranslator.pm) contains methods for translating sequence parameters to dictyBase feature object, locus object, clone attributes or
GenBank sequences. 

=head1 Instantiating a New SeqParamTranslator Object

To instantiate a new SeqParamTranslator object, you may use one of following syntaxes:

my $obj = SeqParamTranslator->new(dbh=>$dbh,
				  query=>$query);


OR


my $obj = SeqParamTranslator->new(dbh=>$dbh,
				  dictyBaseid=>$dictyBaseid);

***** $query can be gene name, orf name, alias name, dictyBaseid or GenBank sequence name.


=head1 Accessor Methods


=head2 type

Usage:

my $type = $obj->type;

This method returns the sequence type for a given sequence name.

* $type can be feature, locus, alias, clone, cds, or gb. 

=head2 locusObject 

Usage:
    
my $locusObj = $obj->locusObject;

if ($locusObj) {

    my $locusName = $locusObj->locus_name;

    my $chr = $locusObj->chromosome;

    my $cm = $locusObj->genetic_position;

    my $desc = $locusObj->description;

    #####

}

This method returns a locus object for a given sequence name.


=head2 featureObject

Usage:

my $featObj = $obj->featureObject; 

if ($featObj) {

    my $strand = $featObj->strand;
    
    my $chr = $locusObj->chromosome;

    my $beg = $featObj->start_coord;

    my $end = $featObj->stop_coord;

    my $dictyBaseid = $featObj->dictyBaseid;

    ####

}

=head2 chromosome 

Usage :

my $chr = $obj->chromosome;

This method returns chrnum for a given clone.


=head2 start_coord 

Usage :

my $beg = $obj->start_coord;

This method returns start_coord for a given sequence name.


=head2 stop_coord 

Usage :

my $end = $obj->stop_coord;

This method returns stop_coord for a given sequence name.

=head2 seqin 

Usage :

my $seqin = $obj->seqin;


This method returns the GenBank sequence name for gcg sequence retrieval for
a Genbank sequence.  


head2 matchList

Usage :

my $matchList = $obj->matchList;

This method returns a matching gene/sequence name list for a given search query.


head2 error

Usage :

my $errMsg = $obj->error;

This method returns an error message for any unknown sequence or dictyBaseid name.


=head1 Author

shuai@genome.stanford.edu

=cut








