#!/usr/bin/perl
package Phenotype;

#####################################################################
# Author : Shuai Weng
# Date   : July 2001
#
# Usage: 
#     
#   use Phenotype;
#
#   ### You may use one of the following syntax 
#   ### instantiate a new Go object.
#
#   my $phObj = Phenotype->new(dbh=>$dbh,
#                              phenotype_no=>$phenotypeNo);
#       
#   OR
#
#   my $phObj = Phenotype->new(dbh=>$dbh,
#                              phenotype=>$phenotype);
#
#
#   ### You can use an accessor for any valid column 
#   ### in the Phenotype table. For example: 
#   my $phenotype = $phObj->phenotype;
#   
#
#   See documentation for detail.
#   
#   http:///usr/local/dicty/www_dictybase/db/lib/html/dictyBase/programmer/Phenotype.html
#
#####################################################################
use strict;
use DBI;
use Carp;
use vars qw (@ISA %allowedConstructors);
use dictyBase_Table;
@ISA = qw (dictyBase_Table); # base class

# Class Globals

# put column names in the hash below, that are able to uniquely
# specify a row in the table

%allowedConstructors = (phenotype_no=>undef,
			phenotype=>undef);


########################################################################
sub getLocusArrayRef {
########################################################################
    my ($self) = @_;
    my $schema = $self->schema;
    my $sth = $self->dbh->prepare("
        SELECT  unique L.locus_no, L.locus_name
        FROM    $schema.locus L, $schema.locus_pheno LP
        WHERE   LP.phenotype_no = ?
        AND     LP.locus_no = L.locus_no
        ORDER BY upper(L.locus_name)
    ");
    $sth->execute($self->phenotype_no);
    my $arrayRef = $sth->fetchall_arrayref();
    $sth->finish;
    return $arrayRef;
}

########################################################################
sub getFeatureArrayRef {
########################################################################
    my ($self, $goid) = @_;
    my $schema = $self->schema;
    my $sth = $self->dbh->prepare("
        SELECT  unique F.feature_no, F.feature_name
        FROM    $schema.feature F, $schema.feat_pheno FP
        WHERE   FP.phenotype_no = ?
        AND     FP.feature_no = F.feature_no
        ORDER BY upper(F.feature_name)
    ");
    $sth->execute($self->phenotype_no);
    my $arrayRef = $sth->fetchall_arrayref();
    $sth->finish;
    return $arrayRef;
}

########################################################################
sub getChr4featureArrayRef {
########################################################################
    my ($self, $goid) = @_;
    my $schema = $self->schema;
    my $sth = $self->dbh->prepare("
        SELECT F.chromosome
        FROM   $schema.feature F, $schema.feat_pheno FP
        WHERE  F.feature_no = FP.feature_no
        AND    FP.phenotype_no = ?
    ");
    $sth->execute($self->phenotype_no);
    my $arrayRef = $sth->fetchall_arrayref();
    $sth->finish;
    return $arrayRef;
}


####################################################################
sub GetReferenceInfo {
####################################################################
    my ($self, %args) = @_;
    my $dbh = $args{'dbh'} || die "A database handle must be passed to GetReferenceInfo method.";
    my $schema = $self->schema;
    my $No = $args{'No'};
    my $phenotypeNo = $args{'phenotype_no'};
    my $phenotypeType = $args{'phenotype_type'};
    my $type = uc($args{'type'});
    my $prikey = "${No}::${phenotypeNo}::${phenotypeType}";
    my $tabNm = $type."_PHENO";
    ### change FEATURE_PHENO to FEAT_PHENO
    $tabNm =~ s/FEATURE/FEAT/;
    my $priKeyCol = $type."_NO::PHENOTYPE_NO::PHENOTYPE_TYPE";
    my $sth = $dbh->prepare("
        SELECT R.reference_no, R.citation
        FROM   $schema.reference R, $schema.reflink RL
        WHERE  RL.primary_key like ?
        AND    RL.tab_name = ?
        AND    RL.primary_key_col = ?
        AND    R.reference_no = RL.reference_no
    ");
    $sth->execute($prikey, $tabNm, $priKeyCol);
    my $arrayRef = $sth->fetchall_arrayref();
    $sth->finish;
    return $arrayRef;
}

####################################################################
sub GetLocusPhenoArrayRef {
####################################################################
    my ($self, %args) = @_;
    my $dbh = $args{'dbh'} || die "A database handle must be passed to 'GetLocusPhenoArrayRef' method.";
    my $schema = $self->schema;
    my $sth;
    if ($args{'filterBy'}) {
	$sth = $dbh->prepare("
            SELECT L.locus_name, LP.locus_no, LP.phenotype_type, 
                   LP.sentence
            FROM   $schema.locus L, $schema.locus_pheno LP
            WHERE  LP.phenotype_no = ?
            AND    upper($args{'searchFor'}) like ?
            AND    LP.locus_no = L.locus_no
            ORDER BY $args{'sortBy'}
        ");
	$sth->execute($args{'phenotype_no'}, 
		      uc($args{'filterBy'}));
    }
    else {
	$sth = $dbh->prepare("
            SELECT L.locus_name, LP.locus_no, LP.phenotype_type, 
                   LP.sentence
            FROM   $schema.locus L, $schema.locus_pheno LP
            WHERE  LP.phenotype_no = ?
            AND    LP.locus_no = L.locus_no
            ORDER BY $args{'sortBy'}
        ");
        $sth->execute($args{'phenotype_no'});
    }
    my $arrayRef = $sth->fetchall_arrayref();
    $sth->finish;
    return $arrayRef;
}

####################################################################
sub GetFeatPhenoArrayRef {
####################################################################
    my ($self, %args) = @_;
    my $dbh = $args{'dbh'} || die "A database handle must be passed to 'GetFeatPhenoArrayRef' method.";
    my $schema = $self->schema;
    my $sth;
    if ($args{'filterBy'}) {
	$sth = $dbh->prepare("
            SELECT F.feature_name, FP.feature_no, 
                   FP.phenotype_type, FP.sentence, F.chromosome
            FROM   $schema.feature F, $schema.feat_pheno FP
            WHERE  FP.phenotype_no = ?
            AND    upper($args{'searchFor'}) like ?
            AND    FP.feature_no = F.feature_no
            ORDER BY F.chromosome, $args{'sortBy'}
        ");
	$sth->execute($args{'phenotype_no'}, 
		      uc($args{'filterBy'}));
    }
    else {
	$sth = $dbh->prepare("
            SELECT F.feature_name, FP.feature_no, 
                   FP.phenotype_type, FP.sentence, F.chromosome
            FROM   $schema.feature F, $schema.feat_pheno FP
            WHERE  FP.phenotype_no = ?
            AND    FP.feature_no = F.feature_no
            ORDER BY F.chromosome, $args{'sortBy'}
        ");
	$sth->execute($args{'phenotype_no'});
    }
    my $arrayRef = $sth->fetchall_arrayref();
    $sth->finish;
    return $arrayRef;
}

####################################################################
sub DeleteAnnotation {
####################################################################
    my ($self, %args) = @_;
    my $dbh = $args{'dbh'} || die "A database handle must be passed to DeleteAnnotation method.";
    my $schema = $self->schema;
    my $refNo = $args{'reference_no'};
    my $phenotypeNo = $args{'phenotype_no'};
    my $phenotypeType = $args{'phenotype_type'};
    my $No = $args{'No'};
    my $type = uc($args{'type'});
    my $NoNm = $type."_NO";
    my $tabNm = $type."_PHENO";
    ### change FEATURE_PHENO to FEAT_PHENO 
    $tabNm =~ s/FEATURE/FEAT/;
    my $priKeyCol = $NoNm."::PHENOTYPE_NO::PHENOTYPE_TYPE";
    my $priKey = "${No}::${phenotypeNo}::${phenotypeType}";
    my $sth = $dbh->prepare("
            DELETE from $schema.reflink
            WHERE  tab_name = ?
            AND    reference_no = ?
            AND    primary_key_col = ?
            AND    primary_key = ?
    ");
    $sth->execute($tabNm, $refNo, $priKeyCol, $priKey);
    $dbh->commit;
    $sth = $dbh->prepare("
            SELECT reference_no
            FROM   $schema.reflink
            WHERE  tab_name = ?
            AND    primary_key_col = ?
            AND    primary_key = ?
    ");
    $sth->execute($tabNm, $priKeyCol, $priKey);
    my $found;
    while(my($thisRefNo) = $sth->fetchrow()) {
	$found++;
	last;
    }
    $sth->finish;
    if (!$found) {
	$sth = $dbh->prepare("
            DELETE from $schema.$tabNm
            WHERE  phenotype_no = ?
            AND    $NoNm = ?
            AND    phenotype_type = ?
        ");
	$sth->execute($phenotypeNo, $No, $phenotypeType);
	$sth->finish;
	$dbh->commit;
    }	
}


####################################################################
sub DESTROY{
####################################################################
# nothing needs to be done 

}


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


=pod

=head1 Name

Phenotype.pm

=head1 Description

This perl object (Phenotype.pm) acts as container for phenotype info associated with a phenotype_no or phenotype in oracle database. Once an object has been instantiated, several methods are available to retrieve the attributes of the object. 


=head1 Instantiating a New Phenotype Object

To instantiate a new Phenotype object, you may use following syntax: 

my $phObj = Phenotype->new(dbh=>$dbh, 
			   $colNm=>$value); 

where $colNm is phenotype_no or phenotype and $dbh is a valid database handle to either dictyBase or SDEV. $value must be a valid value for the column that was provided, otherwise the script will die, with an appropriate error message.
 

Syntax example :

my $phObj = Phenotype->new(dbh=>$dbh, 
			   phenotype_no=>$phenotypeNo);


OR


my $phObj = Phenotype->new(dbh=>$dbh, 
			   phenotype=>$phenotype);


=head1 Accessor Methods


All accessor methods take the form of : 


my $column_value = $phObj->column_name, eg: 


my $phenotypeType = $phObj->phenotype_type; 


etc. You can use an accessor for any valid column in the Phenotype table. 


See valid columns in abstact table:

http:///usr/local/dicty/www_dictybase/db/lib/cgi-bin/dictyBase/tableSpecifications?table=PHENOTYPE

You may use following methods to retrieve other related info.


=head2 getLocusArrayRef

Usage :

foreach my $rowRef (@{$phObj->getLocusArrayRef}) {

    my ($locusNo, $locusNm) = @$rowRef;

    ######
    
}

This method returns loci info for the given phenotype.


=head2 getFeatureArrayRef

Usage :

foreach my $rowRef (@{$phObj->getFeatureArrayRef}) {

    my ($featNo, $featNm) = @$rowRef;

    ######
    
}

=head2 getChr4featureArrayRef

Usage :

foreach my $rowRef (@{$phObj->getChr4featureArrayRef}) {

    my ($chrnum) = @$rowRef;

    ######
    
}

=head2 getRow 

Usage :

my $row = $phObj->getRow;

This method return tab-delimited row for the specified phenotype.


=head2 GetReferenceInfo

Usage :

my $arrayRef = Phenotype->GetReferenceInfo(dbh=>$dbh,
				   phenotype_no=>$phenotypeNo,
				   phenotype_type=>$phenotypeType,
				   type=>$type,
				   No=>$No);


$type = [Feature|Locus]

$No = [$feature_no|$locus_no]


foreach my $rowRef (@$arrayRef) {

    my ($refNo, $citation) = @$rowRef;

    ######

}

This method returns reference_no and citation for the specified phenotype_no, phenotype_type and locus_no/feature_no.


=head2 GetLocusPhenoArrayRef

Usage :

my $arrayRef = Phenotype->GetLocusPhenoArrayRef(dbh=>$dbh,
						phenotype_no=>$phenotypeNo,
						searchFor=>$searchFor,
						filterBy=>$filterBy,
						sortBy=>$sortBy);

$searchFor, $filterBy and $sortBy are optional.

foreach my $rowRef (@$arrayRef) {

    my ($locusNm, $locusNo, $phenotype_type, $sentence, $chrnum) = @$rowRef;

    ######

}


This method returns loci and their associated phenotype info for the given phenotype_no.

=head2 GetFeatPhenoArrayRef

Usage :

my $arrayRef = Phenotype->GetFeatPhenoArrayRef(dbh=>$dbh,
					       phenotype_no=>$phenotypeNo,
					       searchFor=>$searchFor,
					       filterBy=>$filterBy,
					       sortBy=>$sortBy);


$searchFor, $filterBy and $sortBy are optional.

foreach my $rowRef (@$arrayRef) {

    my ($featNm, $featNo, $phenotype_type, $sentence, $chrnum) = @$rowRef;

    ######

}

This method returns features and their associated phenotype info for the given phenotype_no.


=head1 DeleteAnnotation Method

Usage :

eval {

    Phenotype->DeleteAnnotation(dbh=>$dbh,
				reference_no=>$refNo,
				phenotype_no=>$phenotypeNo,
				phenotype_type=>$phenotypeType,
				type=>$type,
				No=>$No);
				

};


$type = [Feature|Locus]

$No = [$feature_no|$locus_no]

This method will delete phenotype annotation associated with specified reference_no, phenotype_no, phenotype_type and feature_no/locud_no.


=head1 Insert, update and delete Methods

You can also use 'Insert' class method and 'update' and 'delete' 
instance methods for inserting new row into database, updating and 
deleting info for a specified row. 

See dictyBase_Table documentation for usage details :

Update : http:///usr/local/dicty/www_dictybase/db/lib/staff/dictyBase/programmer/dictyBase_Table.html#Update_Method

Insert : http:///usr/local/dicty/www_dictybase/db/lib/staff/dictyBase/programmer/dictyBase_Table.html#Insert_Method

Delete : http:///usr/local/dicty/www_dictybase/db/lib/staff/dictyBase/programmer/dictyBase_Table.html#Delete_Method

=head1 Author

Shuai Weng

shuai@genome.stanford.edu

=cut











