#!/usr/bin/perl
package CreateReference;

#######################################################################
##### Author :	Shuai Weng
##### Date   :  Oct. 2000
##### Description : This package contains all necessary methods for dictyBase
#####               curators to create pubmed or unpubmed reference and 
#####               gene_info in oracle. The references include published
#####               and unpublished. 
#####               
#####               This class can handle both individual reference and 
#####               batch loading.
#######################################################################
use strict;
use DBI;
use CGI qw/:all/;
use CGI::Carp qw(fatalsToBrowser);
use lib "/usr/local/dicty/www_dictybase/db/lib/common";
use Login qw (ConnectToDatabase);
use TextUtil qw( DeleteUnwantedChar );
use MedlineParse qw(CreateCitation);
use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase";
use dictyBaseCentralMod qw(:formatPage :getInfo);
use Pubmed;
use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase/curation";
use printReferenceMod qw (:formatSub); 
use lib "/usr/local/dicty/www_dictybase/db/lib/dictyBase/Objects";
use ConfigURLdictyBase;
use Locus;
use Feature;
use Reference;
use Reflink;
use Locus_gene_info;
use Feat_gene_info;
use Abstract;
use Journal;
use Author;
use Author_editor;
use Publication_type;


#######################################################################
#################### global variables #################################
#######################################################################

my $dbh;
my $dblink; 
my $configUrl;
my $createRefUrl;
my $begMedlineUrl;
my $endMedlineUrl;

my %ReferenceNo4Pubmed;

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

	$self = {};
	bless $self;

      	$self->{'_database'} = $args{'database'};
	$self->{'_help'}     = $args{'help'};
	$self->{'_title'}    = defined($args{'title'}) ? 
	                       $args{'title'} : "Reference Creation Page";
	$self->{'_unpubmed'} = defined($args{'unpubmed'}) ? 
	                       $args{'unpubmed'} : '0';
      	$self->{'_batchfile'}= $args{'batchfile'};
	$self->{'_user'}     = $args{'user'};
    	return $self;
}

sub help { $_[0]->{_help} }
sub database { $_[0]->{_database} }
sub title { $_[0]->{_title} }
sub batchfile { $_[0]->{_batchfile} }
sub unpubmed { $_[0]->{_unpubmed} }
sub user { $_[0]->{_user} }

######################################################################
sub DESTROY {   ############ destructor ##############################
######################################################################
    	if (defined $dbh) {
		$dbh->disconnect;
    	}
}

######################################################################
sub start{
######################################################################

    	my ($self) = @_;
	$configUrl = ConfigURLdictyBase->new;
	$dblink = $configUrl->dblink($self->database);
	if (!$self->user) {
	    print "location: ", $configUrl->dictyBaseCGIRoot, "$dblink/curatorLogin\n";
	    print "Content-type: text/html\n\n";
	    exit;
	}
	my ($dbuser, $dbpasswd) = &getUsernamePassword(uc($self->user), 
						       $self->database);
	if (!$dbuser || !$dbpasswd) {
	    print "location: ", $configUrl->dictyBaseCGIRoot, "$dblink/curatorLogin\n";
	    print "Content-type: text/html\n\n";
	    exit;
	}

	if ($self->unpubmed == 1) {
	    $createRefUrl = $configUrl->dictyBaseCGIRoot."$dblink/curation/createUnPubMedRef";
	    if (param('Submit')) {
		$dbh = &ConnectToDatabase($self->database, $dbuser, $dbpasswd);
		$self->createUnPubMedReference;
	    }
	    else {
		$dbh = &ConnectToDatabase($self->database);
		$self->displayUnPubMedEntryForm;
	    }
	}
	else {
	     $createRefUrl = $configUrl->dictyBaseCGIRoot."$dblink/curation/createPubMedRef";
	    if (param('Submit')) {

		$dbh = &ConnectToDatabase($self->database, $dbuser, $dbpasswd);

		$begMedlineUrl = $configUrl->ncbiUrlRoot.'query.fcgi?cmd=Text&db=PubMed&uid=';
		$endMedlineUrl = '&dopt=Medline';

		$self->createPubMedReference;
	    }
	    else {
		$self->displayPubMedEntryForm;
	    }
	}
}

#######################################################################
sub displayPubMedEntryForm {
#######################################################################

        my ($self) = shift;

	&printStartPage($self->database, $self->title, $self->help);

	my %typeLabels = ('Locus'=>'Locus or locus_no',
			  'Feature'=>'Feature or feature_no');
	my @typeValues = qw/Locus Feature/;
	my $defaultType = param('type');
	if ($defaultType) { $defaultType = "\u$defaultType"; }
	else { $defaultType = "Locus"; }

	my $feat = param('feat');

        ##########################
	print 
	startform({-method=>'POST',
		   -action=>$createRefUrl}),
	b("This form is for dictyBase curators to retrieve pubmed reference(s) from NCBI, load reference and gene info into oracle database."),p,
        b(font({-size=>"+1"}, 'Enter ')),
	popup_menu(-name=>'type',
                   -"values"=>\@typeValues,
                   -default=>$defaultType,
                   -labels=>\%typeLabels
                  ), b(": "),      
        textfield(-name=>'feat', -value=>"$feat", -size=>15),
	b(' and PubMed ID : '),
	textfield(-name=>'pubmed', -size=>15),
	p,
	center(b(font({color=>"red", size=>'+4'}, "OR"))),
	b(font({-size=>"+1"}, 'Enter batch file name * : ')),
	textfield(-name=>'batchfile', -size=>52),
	p,
      
	hidden('user', "$self->user"),   
	submit('Submit','Submit'), " ",
	reset,

	endform,
	p,
		       b(font({color=>'red'}, "* Note: The format for batch file is 'pubmedID[tab]LocusORfeatureNm'. You have to enter full path name for this file."));
	&printEndPage;
}

#######################################################################
sub createPubMedReference {
#######################################################################
    my ($self) = shift;
    
    $self->getReferenceList;
   
    my $loadRefNum;
    my $loadGeneInfoNum;

    my $unloadRefNum;
    my $unloadGeneInfoNum;

    my $badJournalNum;
    my $badReferenceNum;
    my $inDBnum;
    my $locusNotFoundNum;

    #################################################################
    ############## Loading from web #################################
    #################################################################

    my $feat = param('feat');
    my $pubmed = param('pubmed');
    my $batchfile = param('batchfile');
    if (!$batchfile && (!$feat || !$pubmed)) {
	$self->err_report("You have to enter locus/feature and pubmed id
OR enter batch file name before press '".b("submit")."' button. Please go back, enter all necessary info and try again.");
	exit;
    }
    if (!$batchfile) {
	my $checkNo = $self->setTypeLocusORfeatureNo($feat);
	if ($checkNo == -1) {
	    $self->err_report("The locus/feature name or number you entered '".font({-color=>'red'}, $feat)."' is not found in database. Please go back, fix it and try it again.");
	    exit;
	}
    }    
    elsif (!-e "$batchfile") {
	$self->err_report("The '$batchfile' does not exist. Please check and correct the file name, file path and try it again. Thanks!<p>");
	exit;
    }

    &printStartPage($self->database, $self->title, $self->help);

    print `date`, p;
    
    if ($batchfile) {
	open(IN, "$batchfile") || 
	    die "Can't open '$batchfile' for reading:$!", p;
	my $date = `date +%Y%m%d`;
	my $db = lc($self->database);

	my $logfile = "/share/$db/logs/pubmed.log";
	my $errlogfile = "/share/$db/logs/pubmed.errlog";

	open(LOG, ">>$logfile") ||
	    die "Can't open '$logfile' for writing:$!\n";
	open(ERR, ">>$errlogfile") ||
	    die "Can't open '$errlogfile' for writing:$!\n";

	print "The loading details and loading summary will be stored in logfile:", br, b(font({-color=>'red'}, $logfile)), p;
	print "The error log will stored in error log file :", br, b(font({-color=>'red'}, $errlogfile)), p; 

	while(<IN>) {
	    chomp;
	    my $line = $_;
	    my ($pubmed, $feat) = split(/\t/, $line);
	    if (!$pubmed || !$feat) { next;}
	    my $refObject = Pubmed->new(dbh=>$dbh,
				        pubmed=>$pubmed);
	    my $refNo = $refObject->referenceNo;
	    my $msg = $refObject->error;
	    if ($msg =~ /^::refexist/i) {
		print "pubmed id = $pubmed is alreday in database.", br;
		print LOG "pubmed id = $pubmed is alreday in database.\n";
                $inDBnum++;
                my $checkNo = $self->setTypeLocusORfeatureNo($feat);
                if ($checkNo == -1) {
		    print "locus or feature name $feat is not found in database.", br;
		    print LOG "locus or feature name $feat is not found in database.\n";
		    print ERR "locus or feature name $feat is not found in database.\n";
		    $locusNotFoundNum++;
		}
		else {
		    my @tag = $self->checkGeneInfo($refNo);
		    if ($#tag < 0) {
			print "Gene info for '$line' has been inserted into database.", p;
			print LOG "Gene info for '$line' has been inserted into database.\n\n";
		    }
		    else {
			print "The gene info for '$line' is already in the database.", p;
			print LOG "The gene info for '$line' is already in the database\n\n";
		    }
		}
		next;
	    }
	    my $checkNo = $self->setTypeLocusORfeatureNo($feat);
	    if ($checkNo == -1) {
		print "locus or feature name $feat is not found in database.", br;
		print LOG "locus or feature name $feat is not found in database.\n";
		print ERR "locus or feature name $feat is not found in database.\n";
		$locusNotFoundNum++;
		next;
	    }
	    if ($msg =~ /::journal/i) {
		print "entry '$line' can not be loaded into database because the journal can't be inserted into database.",br;
		print LOG "entry '$line' can not be loaded into database because the journal can't be inserted into database.\n";
		print ERR "entry '$line' can not be loaded into database because the journal can't be inserted into database.\n";
		$badJournalNum++;
		next;
	    }
	    if ($msg =~ /::reference/i) {
		print "entry '$line' can not be loaded into database because the reference can't be inserted into database.", br;
		print LOG "entry '$line' can not be loaded into database because the reference can't be inserted into database.\n";
		print ERR "entry '$line' can not be loaded into database because the reference can't be inserted into database.\n";
		$badReferenceNum++;
		next;
	    }
	    $loadRefNum++;
	    print "Reference info for pubmed id = $pubmed has been inserted into reference and its related tables.",p;
	    print LOG "Reference info for pubmed id = $pubmed has been inserted into reference and its related tables.\n\n";
	    ############ Insert into locus_gene_info or feat_gene_info
	    my $geneinfo;
	    if ($self->{'_type'} =~ /Locus/i) {
		$geneinfo = $self->insertLocusGeneInfo($self->{'_No'}, 
						       $refNo);
	    }
	    else {
		$geneinfo = $self->insertFeatGeneInfo($self->{'_No'}, 
						      $refNo);
	    }
	    if ($geneinfo == 1) {
		print "Gene info for '$line' has been inserted into ";
		print LOG "Gene info for '$line' has been inserted into ";
		if ($self->{'_type'} =~ /locus/i) {
		    print "locus_gene_info table.",p;
		    print LOG "locus_gene_info table.\n\n";
		}
		else {
		    print "feat_gene_info table.",p;
		    print LOG "feat_gene_info table.\n\n";
		}
		$loadGeneInfoNum++;
	    }
	    else {
		print "The gene info for entry pubmed id = $pubmed and locus=$feat can not be loaded into database.:$geneinfo", br;
		print LOG "The gene info for entry pubmed id = $pubmed and locus=$feat can not be loaded into database.:$geneinfo\n";
		print ERR "The gene info for entry pubmed id = $pubmed and locus=$feat can not be loaded into database.:$geneinfo\n";
		$unloadGeneInfoNum++;
	    }
	}
	close(IN);
	print p, b("Loading Summary:"), p;
	print LOG "\n\nLoading Summary:\n\n";
	if ($loadRefNum) {
	    print "Total $loadRefNum references have been loaded into reference and related tables.", br;
	    print LOG "Total $loadRefNum references have been loaded into reference and related tables.\n";
	}
	if ($inDBnum) {
	    print "...... $inDBnum entries are already in database.", br;
	    print LOG "...... $inDBnum entries are already in database.\n"; 
	}
	if ($locusNotFoundNum) {
	    print "...... $locusNotFoundNum loci are not found in database.", br;
	    print LOG "...... $locusNotFoundNum loci are not found in database.\n"; 
	}
	if ($badJournalNum) {
	    print "...... $badJournalNum entries are not loaded into database because the journal can't be inserted into journal table.", br;
	    print LOG "...... $badJournalNum entries are not loaded into database because the journal can't be inserted into journal table.\n";
	}
	if ($badReferenceNum) {
	    print "...... $badReferenceNum entries are not loaded into database because the reference info can't be inserted into reference table.", p;
	    print LOG "...... $badReferenceNum entries are not loaded into database because the reference info can't be inserted into reference table.\n";
	}
	if ($loadGeneInfoNum) {
	    print br, "Total $loadGeneInfoNum gene info have been loaded into database.", br;
	    print LOG "\nTotal $loadGeneInfoNum gene info have been loaded into database.\n";
	}
	if ($unloadGeneInfoNum) {
	    print "...... $unloadGeneInfoNum gene info can not be loaded into database due to inserting errors.", br;
	    print LOG "...... $unloadGeneInfoNum gene info can not be loaded into database due to inserting errors.\n";
	}
	close(LOG);
    }
    else {
	my $refObject = Pubmed->new(dbh=>$dbh,
				    pubmed=>$pubmed);
	my $refNo = $refObject->referenceNo;
	my $msg = $refObject->error;
	if ($msg !~ /^::refexist/i) {
	    if ($msg =~ /::reference/i) {
		print "The pubmed reference for pubmed Id = $pubmed can not be loaded into database.", br, $msg, br; 
	    }
	    elsif ($msg =~ /::journal/i) {
		print "The journal info for pubmed Id = $pubmed can not be loaded into database.", br, $msg, br;
            }
	    elsif ($msg =~ /::author/i) {
		print "The author info for pubmed Id = $pubmed can not be loaded into database.", br, $msg, br;
            }
	    elsif ($msg =~ /::editor/i) {
		print "The author_editor info for pubmed Id = $pubmed can not be loaded into database.", br, $msg, br;
            }
	    elsif ($msg =~ /::url/i) {
		print "The url info for pubmed Id = $pubmed can not be loaded into database.", br, $msg, br;
            }
	    elsif ($msg =~ /::pubtype/i) {
		print "The pubtype info for pubmed Id = $pubmed can not be loaded into database.", br, $msg, br;
            }
	    else {
		print "The pubmed reference for pubmed Id = $pubmed have been loaded into reference and its related tables.", p;
	    }
	    ############ Insert into locus_gene_info or feat_gene_info
	    my $geneinfo;
	    if ($self->{'_type'} =~ /Locus/i) {
		$geneinfo = $self->insertLocusGeneInfo($self->{'_No'}, 
						       $refNo);
	    }
	    else {
		$geneinfo = $self->insertFeatGeneInfo($self->{'_No'}, 
						      $refNo);
	    }
	    if ($geneinfo == 1) {
		print "The gene info for pubmed id = $pubmed and ";
		if ($self->{'_type'} =~ /locus/i) {
		    print "locus = $feat have been loaded into locus_gene_info table.", p;
		}
		else {
		    print "feature = $feat have been loaded into feat_gene_info table.", p;
		}
	    }
	    else {
		print "The gene info for entry pubmed id = $pubmed and locus=$feat can not be loaded into database.:$geneinfo", br;
	    }
	}
	else {
	    print "The pubmed you entered (<font color=red>$pubmed</font>) is already in database.", p;
	    my @tag = $self->checkGeneInfo($refNo);
	    if ($#tag < 0) {
		print "Gene info for pubmed=$pubmed and locus/feature=$feat has been inserted into database.", p;
		print LOG "Gene info for pubmed=$pubmed and locus/feature=$feat has been inserted into database.\n\n";
	    }
	    else {
		print "The gene info for pubmed=$pubmed and locus/feature=$feat is already in the database.", p;
		print LOG "The gene info for pubmed=$pubmed and locus/feature=$feat is already in the database\n\n";
	    }
	}
    }
    print p, `date`, p;
    ##################
 
    print p,b("Return to ".a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/curatorLogin?user=".$self->user}, "dictyBase Curator Central")), br;
    &printEndPage;
}

#######################################################################
sub displayUnPubMedEntryForm {
#######################################################################

        my ($self) = shift;

	&printStartPage($self->database, $self->title, $self->help);

	my $feat = param('feat');

     
        ##########################
	print 
	startform({-method=>'POST',
		   -action=>$createRefUrl}),
	font({-size=>'+1'}, "This form is for dictyBase curators to load a non-pubmed reference into oracle database. If the status of the paper is 'Published', a new row in the relevant gene info table will be created. If the status is anything else (eg. unpublished, in press), the paper will be linked to the gene via the REFLINK table."),p,
	b(font({-color=>'red'}, "NOTE: if you want to add a book or a book chapter, use ".a({-href=>''}, "this page")." (now under construction).")),p,
	center(b(font({color=>'red', size=>"+4"}, 'Enter')));

	$self->printGeneName;	
	&author();
	&refTitle();
	print table(&journal().
		    &volume().
		    &page().
		    &year());
	&abstract();
	&publishedStatus();
	&pubType;
       
        print  
	p, center(b(font({color=>"red", size=>'+4'}, "OR"))),
	b(font({-size=>"+1"}, 'Enter batch file name * : ')),
	textfield(-name=>'batchfile', -size=>52),
	p,
      
	hidden(-name=>'user', 
	       -value=>$self->user),   
	submit('Submit','Submit'), " ",
	reset,

	endform,
	p,
	b("* Note: The format for batch file is :"), br, b(font({color=>'red'}, "reference.title[tab]journal.abbreviation[tab]reference.volume[tab]reference.page[tab]reference.year[tab]reference.citation<br>[tab]author.author_name[tab]locus.locus_name[tab]publication_type.pub_type[tab]reference.status[tab]<br>reference.ref_source[tab].")), br, b("You have to enter full path name for this file."), p;
	&printEndPage;
}

#######################################################################
sub createUnPubMedReference {
#######################################################################
    my ($self) = shift;
    
    #################################################################
    ############## Loading from web #################################
    #################################################################

    my $feat = param('feat');
    my $batchfile = param('batchfile');
    my $reftitle = param('reftitle');
    my $journal = param('journal');
    my @author;
    for (my $i = 1; $i <= 12; $i++) {
	if (param("author$i")) {
	    push(@author, param("author$i"));
	}
    }
    if (!$batchfile && (!$feat || !@author) ) {
	$self->err_report("You have to enter locus/feature and reference info OR enter batch file name before press '".b("submit")."' button. Please go back, enter all necessary info and try again.");
	exit;
    }
    if (!$batchfile) {
	my $checkNo = $self->setTypeLocusORfeatureNo($feat);
	if ($checkNo == -1) {
	    $self->err_report("The locus/feature name or number you entered '".font({-color=>'red'}, $feat)."' is not found in database. Please go back, fix it and try it again.");
	    exit;
	}
	elsif (!param('year')) {
	    $self->err_report("You have to enter year before press the ".b("submit")." button. Please go back, enter the year and try again.");
	    exit;
	}
    }    
    elsif (!-e "$batchfile") {
	$self->err_report("The '$batchfile' does not exist. Please check and correct the file name, file path and try it again. Thanks!<p>");
	exit;
    }

    &printStartPage($self->database, $self->title, $self->help);

    print `date`, p;
    
    if (!$batchfile) {
	my $reftitle = param('reftitle');
	my $journal = param('journal');
	my $volume = param('volume');
	my $page = param('page');
	my $year = param('year');
	my $reftype = param('reftype');
	my $refsource = "Curator";
	my @pubtype = param('pubtype'); 
	my $abstract = param('abstract');

	my @authors;
	for (my $i = 1; $i <= 6; $i++) {
	    my $author = param("author$i");
	    $author =~ s/[\.\,\;]//g;
	    &DeleteUnwantedChar(\$author);
	    if (!$author) {  next; }
	    push(@authors, $author);
	}
      
	if ($journal =~ /^[0-9]+$/) {
	    my $journalObj = Journal->new(dbh=>$dbh,
					  journal_no=>$journal);
	    if (!$journalObj) {
		print "The journal_no = $journal is not found in database:$@", br;
		return ;
	    }
	    $journal = $journalObj->abbreviation;
	}
        my $issue;
	my $citation = &CreateCitation(\$year, \$reftitle, \$journal, 
				  \$volume, \$issue, \$page, \@authors);
	$self->InsertUnPubMedInfo($refsource, $reftype,
				  $citation, $reftitle, $journal, 
				  $volume, $page, $year, $abstract, 
				  \@authors, \@pubtype);
    }
    else {
	open(IN, "$batchfile") || 
	    die "Can't open '$batchfile' for reading:$!", p;
	my $date = `date +%Y%m%d`;
	my $db = lc($self->database);

	my $logfile = "/share/$db/logs/unpubmed.log";
	my $errlogfile = "/share/$db/logs/unpubmed.errlog";
	
	open(LOG, ">>$logfile") ||
	    die "Can't open '$logfile' for writing:$!\n";
	open(ERR, ">>$errlogfile") ||
	    die "Can't open '$errlogfile' for writing:$!\n";

	print "The loading details and loading summary will be stored in logfile:", br, b(font({-color=>'red'}, $logfile)), p;
	print "The error log will stored in error log file :", br, b(font({-color=>'red'}, $errlogfile)), p; 

	my $loadRefNum;
	my $loadReflinkNum;
	my $loadGeneinfoNum;
       	my $unloadReflinkNum;
	my $unloadGeneinfoNum;
       	
	my $badJournalNum;
	my $badReferenceNum;
	my $locusNotFoundNum;

	my @authors;
        my @pubtype;
        my @feat;
	my %feat4citation;
        my %author4citation;
        my %pubtype4citation;
	my ($reftitle, $journal, $volume, $page, $year, $citation, 
	    $author, $feat, $pubtype, $reftype, $refsource);
	my ($PREpage, $PREreftitle, $PREjournal, $PREvolume, $PREyear, 
	    $PREcitation, $PREauthor, $PREfeat, $PREpubtype, $PREreftype, 
	    $PRErefsource);
	while(<IN>) {
	    chomp;
	    if ($_ =~ /^ *$/) {
		next;
	    }
	    ###### each paper/reference is listed multiple times 
	    ###### for multiple authors or loci
            ###### how about the pub_type ???, 
	    ($reftitle, $journal, $volume, $page, $year, $citation, $author, 
	     $feat, $pubtype, $reftype, $refsource) = split(/\t/);	    
	    #########################
	    if (!$citation) { next; }
	    #########################
	    if ($PREcitation ne $citation && $PREcitation) {
		my $abstract;
		my $return = $self->InsertUnPubMedInfo($PRErefsource, 
				  $PREreftype, $PREcitation, $PREreftitle, 
			          $PREjournal, $PREvolume, $PREpage, 
				  $PREyear, $abstract,
				  \@authors, \@pubtype, \@feat, "1");
		if ($return =~ /journal/i) { $badJournalNum++; }
		elsif ($return =~ /reference/i) { $badReferenceNum++; }
		else { 
		    $loadRefNum++; 
		    if ($return =~ /^reflink:([0-9]+):([0-9]+):([0-9]+)$/) {
			$locusNotFoundNum += $1;
			$unloadReflinkNum += $2;
			$loadReflinkNum += $3;
		    }
		    elsif ($return =~ /^geneinfo:([0-9]+):([0-9]+):([0-9]+)$/){
			$locusNotFoundNum += $1;
			$unloadGeneinfoNum += $2;
			$loadGeneinfoNum += $3;
		    }
		}
		undef @authors;
		undef @pubtype;
		undef @feat;
		undef %feat4citation;
		undef %author4citation;
		undef %pubtype4citation;
	    }
	    $author =~ s/[\.\;\,]//g;
	    if (!$author4citation{"$author:$citation"}) {
		push(@authors, $author);
		$author4citation{"$author:$citation"}++;
	    }
	    if (!$feat4citation{"$feat:$citation"}) {	
		push(@feat, $feat);
	        $feat4citation{"$feat:$citation"}++;
	    }
	    if (!$pubtype4citation{"$pubtype:$citation"}) {
		push(@pubtype, $pubtype);
		$pubtype4citation{"$pubtype:$citation"}++;
            }
	    $PREcitation = $citation;
	    $PRErefsource = $refsource;
	    $PREreftype = $reftype;
	    $PREreftitle = $reftitle;
	    $PREjournal = $journal;
	    $PREvolume = $volume;
	    $PREpage = $page;
	    $PREyear = $year;
	}
	if ($PREreftype) {
	    my $abstract;
	    my $return = $self->InsertUnPubMedInfo($PRErefsource, 
				  $PREreftype, $PREcitation, $PREreftitle, 
			          $PREjournal, $PREvolume, $PREpage, $PREyear, 
				  $abstract, \@authors, \@pubtype, 
				  \@feat, "1");
	    if ($return =~ /journal/i) { $badJournalNum++; }
	    elsif ($return =~ /reference/i) { $badReferenceNum++; }
	    else { 
		$loadRefNum++; 
		if ($return =~ /^reflink:([0-9]+):([0-9]+):([0-9]+)$/) {
		    $locusNotFoundNum += $1;
		    $unloadReflinkNum += $2;
		    $loadReflinkNum += $3;
		}
		elsif ($return =~ /^geneinfo:([0-9]+):([0-9]+):([0-9]+)$/){
		    $locusNotFoundNum += $1;
		    $unloadGeneinfoNum += $2;
		    $loadGeneinfoNum += $3;
		}
	    }
        }
	close(IN);
	########## SUMMARY ##########
	print p, "Loading Summary:", p;
	print LOG "\n\nLoading Summary:\n\n";
	if ($loadRefNum) {
	    print "Total $loadRefNum reference info have been loaded into reference and related tables.", p;
	    print LOG "Total $loadRefNum reference info have been loaded into reference and related tables.\n\n";
	}
	if ($badJournalNum) {
	    print "****** $badJournalNum entries can't be inserted into journal table. See error log for detail.", p;
	    print LOG "****** $badJournalNum entries can't be inserted into journal table. See error log for detail.\n\n";
	}
	if ($badReferenceNum) {
	    print "****** $badReferenceNum entries can't be inserted into reference table. See error log for detail.", p;
	    print LOG "****** $badReferenceNum entries can't be inserted into reference table. See error log for detail.\n\n";
	}
	if ($locusNotFoundNum) {
	    print "$locusNotFoundNum loci/features can't be found in database.", p;
	    print LOG "$locusNotFoundNum loci/features can't be found in database. See error log for detail.\n\n";
        }
	if ($loadGeneinfoNum) {
	    print "Total $loadGeneinfoNum gene info have been inserted into database.", p;
	    print LOG "Total $loadGeneinfoNum gene info have been inserted into database.\n\n";
	}
	if ($unloadGeneinfoNum) {
	    print "****** $unloadGeneinfoNum gene info can't be loaded into database. See error log for detail.", p;
	    print LOG "****** $unloadGeneinfoNum gene info can't be loaded into database. See error log for detail.\n\n";
        }
	if ($loadReflinkNum) {
	    print "Total $loadReflinkNum reflink info have been inserted into database.", p;
	    print LOG "Total $loadReflinkNum reflink info have been inserted into database.\n\n";
	}
	if ($unloadReflinkNum) {
	    print "****** $unloadReflinkNum reflink info can't be loaded into database. See error log for detail.", p;
	    print LOG "****** $unloadReflinkNum reflink info can't be loaded into database. See error log for detail.\n\n";
	}
	#############################
	close(LOG);
	close (ERR);
    }

    print p, `date`, p;
    ##################
    print p,b("Return to ".a({-href=>$configUrl->dictyBaseCGIRoot."$dblink/curatorLogin?user=".$self->user}, "dictyBase Curator Central")), br;
    &printEndPage;
}

########################################################################
sub InsertUnPubMedInfo {
########################################################################
    my ($self, $refsource, $reftype, $citation, $reftitle, $journal, 
	$volume, $page, $year, $abstract, $authorRef, $pubtypeRef, 
	$featRef, $batch) = @_;

    if (!$year) { 
	print "The reference info can't be inserted into database due to the missing year info.",p;
	return;
    }

    my $refNo = $self->insertRefInfo($authorRef, $citation, $reftitle, 
				     $journal, $volume, $page, $year, 
				     $abstract, $reftype, $refsource, 
				     @$pubtypeRef); 
			    	   
    if ($refNo) {
	if (!$batch) {
	    print "Reference info has been inserted into reference table.", p;
	}
	else  {
	    print "Reference info for citation='$citation' has been inserted into reference table.\n";
	    print LOG "Reference info for citation='$citation' has been inserted into reference table.\n";
	}
    }
    else {
	print "Error occurred when inserting reference info for citation='$citation' into reference table.", p;
	if ($batch) {
	    print LOG "Error occurred when inserting reference info for citation='$citation' into reference table. \n";
	    print ERR "Error occurred when inserting reference info for citation='$citation' into reference table. \n";
	}
	return "reference";
    }
    
    if (!$batch) {
	$self->InsertGeneInfoORrefLink($refNo, $reftype);
    }
    else {
	my $locusNotFound = 0;
	my $reflinkFail = 0;
	my $reflinkSuccess = 0;
	my $geneinfoFail = 0;
	my $geneinfoSuccess = 0;
	foreach my $feat (@$featRef) {
            my $checkNo = $self->setTypeLocusORfeatureNo($feat);
	    if ($checkNo == -1) { 
		print "The locus/feature $feat is not found in database.",p;
		print LOG "The locus/feature $feat is not found in database.\n\n";
		print ERR "The locus/feature $feat is not found in database.\n\n";
		$locusNotFound++;
		next;
            }
	    else {
		my $checkERR = $self->InsertGeneInfoORrefLink($refNo, 
						    $reftype, $batch);
		if ($checkERR =~ /reflinkFail/i) {
		    $reflinkFail++;
		}
		elsif ($checkERR =~ /reflinkSuccess/i) {
		    $reflinkSuccess++;
		}
		elsif ($checkERR =~ /geneinfoFail/i) {
		    $geneinfoFail++;
		}
		elsif ($checkERR =~ /geneinfoSuccess/i) {
		    $geneinfoSuccess++;
		}
	    }
        }
	if ($reftype !~ /^published/i) {
	    return "reflink:$locusNotFound:$reflinkFail:$reflinkSuccess";
	}
	else {
	    return "geneinfo:$locusNotFound:$geneinfoFail:$geneinfoSuccess";
	}
    }
}

########################################################################
sub insertRefInfo {
########################################################################
    my ($self, $authorRef, $citation, $reftitle, $journal, $volume, 
	$page, $year, $abstract, $reftype, $refsource, @pubtype) = @_;
	
    my $journalNo;
    if ($journal =~ /^[0-9]+$/) {
	$journalNo = $journal;
	my $journalObj = Journal->new(dbh=>$dbh,
				      journal_no=>$journalNo);
	if (!$journalObj) {
	    print "The journal_no = $journalNo is not found in database:$@", br;
	    return ;
	}
	$journal = $journalObj->abbreviation;
    }
    else {
	$journalNo = $self->insertJournal($journal);
    }
    if (!$citation) {
	my $issue;
	$citation = &CreateCitation(\$year, \$reftitle, \$journal, 
				   \$volume, \$issue, \$page, 
				   $authorRef);
    }
    my $refNo = Reference->GetRefNoBYcitation(dbh=>$dbh, 
					      citation=>$citation);
    if ($refNo) { return $refNo; } 
    eval {
	Reference->Insert(dbh=>$dbh,
			  literals=>{reference_no=>'CGM_DDB.refno_seq.nextval'},
			  binds=>{ref_source=>$refsource,
			          status=>$reftype,
			          citation=>$citation,
			          year=>$year,
			          page=>$page,
			          volume=>$volume,
			          title=>$reftitle,
			          journal_no=>$journalNo});
    };
    if ($@) {
	 print "An error occurred when inserting reference info for citation='$citation' into database:$@", br;
	 return ;
    }
    else {
	print "The reference info or citation = '$citation' has been inserted into database.",br;
	 $dbh->commit;
	 my $sth = $dbh->prepare("
             SELECT CGM_DDB.refno_seq.currval
             FROM   dual
         ");
	 $sth->execute;
	 $refNo = $sth->fetchrow();
	 if (!$refNo) { return;}
    }
    if ($abstract) { 
	$self->insertAbstract($refNo, $abstract);
    }
    foreach my $type (@pubtype) {
	eval {
	    Publication_type->Insert(dbh=>$dbh,
				     binds=>{reference_no=>$refNo,
					     pub_type=>$type});
	};
	if ($@) {
	    print "An error occurred when inserting pub_type = '$type' for reference_no = $refNo into database:$@", br;
	    $dbh->rollback;
	}
	else {
	    print "The pub_type = '$type' for reference_no = $refNo has been inserted into database.", br;
	    $dbh->commit;
	}
    }
    my $order;
    foreach my $author (@$authorRef) {
	$order++;
	my $authorNo = $self->insertAuthor($author);
	if ($authorNo) {
	    $self->insertAuthorEditor($authorNo, $refNo, $order);
	}
    }
    return $refNo;
}

########################################################################
sub insertAuthor {
########################################################################
    my ($self, $author) = @_;
    my $authorObj = Author->new(dbh=>$dbh,
				author_name=>$author);
    if ($authorObj) {
	return $authorObj->author_no;
    }
    eval {
	Author->Insert(dbh=>$dbh,
		       literals=>{author_no=>'CGM_DDB.authorno_seq.nextval'},
		       binds=>{author_name=>$author});
    };
    if ($@) {
	print "An error occurred when inserting author '$author' into database:$@", br;
	$dbh->rollback;
	return ;
    }
    else {
	print "The author '$author' has been inserted into database.", br;
	$dbh->commit;
	my $authorObj = Author->new(dbh=>$dbh,
				    author_name=>$author);
	return $authorObj->author_no;
    }
}

########################################################################
sub insertAuthorEditor {
########################################################################
    my ($self, $authorNo, $refNo, $order) = @_;
    eval {
	Author_editor->Insert(dbh=>$dbh,
			      binds=>{author_no=>$authorNo,
				      reference_no=>$refNo,
				      author_type=>'Author',
				      author_order=>$order});
    };
    if ($@) {
	print "An error occurred when inserting author_no = $authorNo, reference_no = $refNo, author_type = 'Author' and author_order = $order into author_editor table:$@", br;
	$dbh->rollback;
    }
    else {
	print "The new author_editor entry for author_no = $authorNo, reference_no = $refNo, author_type = 'Author' and author_order = $order has been inserted into database.", br;
	$dbh->commit;
    }
}


########################################################################
sub insertJournal {
########################################################################
    my ($self, $journal) = @_;

    if (!$journal) { return; }

    my $journalObj = Journal->new(dbh=>$dbh,
				  abbreviation=>$journal);
    if ($journalObj) { 
	return $journalObj->journal_no;
    }
    my ($abbrev, $issn, $Jtitle) = &findFullJournalInfo($journal);
    eval {
	Journal->Insert(dbh=>$dbh,
			literals=>{journal_no=>'CGM_DDB.journalno_seq.nextval'},
			binds=>{abbreviation=>$abbrev,
			        issn=>$issn,
			        full_name=>$Jtitle});
    };
    if ($@) {
	print "An error occurred when inserting journal '$journal' into database:$@", br;
	$dbh->rollback;
	return;
    }
    else {
	print "The new journal '$journal' has been inserted into database.", br;
	$dbh->commit;
	my $journalObj = Journal->new(dbh=>$dbh,
				      abbreviation=>$journal);
	if ($journalObj) { return $journalObj->journal_no; }
    }
}

########################################################################
sub insertAbstract {
########################################################################
    my ($self, $refNo, $abstract) = @_;
    eval {
	Abstract->Insert(dbh=>$dbh,
			 binds=>{reference_no=>$refNo,
				 abstract=>$abstract});
    };
    if ($@) {
	print "An error occurred when inserting abstract '$abstract' into database:$@", br;
	$dbh->rollback;
    }
    else {
	print "The abstract has been inserted into database.", br;
	$dbh->commit;
    }  
}

########################################################################
sub InsertGeneInfoORrefLink {
########################################################################
    my ($self, $refNo, $reftype, $batch) = @_;
    if ($reftype =~ /^published/i) {
	############ Insert into locus_gene_info or feat_gene_info
	my $geneinfoERR;
	if ($self->{'_type'} =~ /Locus/i) {
	    $geneinfoERR = $self->insertLocusGeneInfo($self->{'_No'}, $refNo);
	}
	else {
	    $geneinfoERR = $self->insertFeatGeneInfo($self->{'_No'}, $refNo);
	}
	if ($geneinfoERR == 1) {   
	    print "The gene info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo has been inserted into database.", p; 
	    if ($batch) {
		print LOG "The gene info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo has been inserted into database.\n\n";
		return "geneinfoSuccess";
	    }
	}
	else {
	    print "Error occurred when inserting gene info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo. See following error message.", br, $geneinfoERR, p;
	    if ($batch) {
		print LOG "Error occurred when inserting gene info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo. See following error message.\n$geneinfoERR\n\n";
		print ERR "Error occurred when inserting gene info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo. See following error message.\n$geneinfoERR\n\n";
		return "geneinfoFail";
	    }
	}
    }
    else {
	############ Insert into reflink table
	my $reflinkERR = $self->insertRefLink($refNo, $self->{'_No'}, 
					   $self->{'_type'});
	if ($reflinkERR == 1) {
	    print "The reflink info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo has been inserted into database.", p; 
	    if ($batch) {
		print LOG "The reflink info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo has been inserted into database.\n\n"; 
		return "reflinkSuccess";
	    }
	}
	else {
	    print "Error occurred when inserting reflink info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo. See following error message.", br, $reflinkERR, p;
	    if ($batch) {
		print LOG "Error occurred when inserting reflink info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo. See following error message.\n$reflinkERR\n\n";
		print ERR "Error occurred when inserting reflink info for ", $self->{'_type'}, "_no=", $self->{'_No'}, " and reference_no=$refNo. See following error message.\n$reflinkERR\n\n";
		return "reflinkFail";
	    }
	}
    }
}

########################################################################
sub setTypeLocusORfeatureNo {
########################################################################
    my ($self, $name) = @_;
    if (param('type') && !param('batchfile') ) {
	$self->{'_type'} = param('type');
	&DeleteUnwantedChar(\$name);
	if (param('type') =~ /locus/i) {
	    if ($name =~ /^[0-9]+$/) {
		my $locusObj = Locus->new(dbh=>$dbh,
					  locus_no=>$name);
		if (!$locusObj) { return -1; } 
		$self->{'_No'} = $name;
            }
	    else {
		my $locusObj = Locus->new(dbh=>$dbh,
					  locus_name=>$name);
		if(!$locusObj) { return -1; }
		$self->{'_No'} = $locusObj->locus_no;
            }
	}
	else {
	    if ($name =~ /^[0-9]+$/) {
	        my $featObj = Feature->new(dbh=>$dbh,
					   feature_no=>$name);
		if(!$featObj) { return -1; }
		$self->{'_No'} = $name;
            }
	    else {
		my $featObj = Feature->new(dbh=>$dbh,
					   feature_name=>$name);
		if(!$featObj) { return -1; }
		$self->{'_No'} = $featObj->feature_no;
            }
	} 
    }
    else { ### for the locus/feature name listed in batch file
	my $locusObj = Locus->new(dbh=>$dbh,
				  locus_name=>$name);
	if (!$locusObj) {
	    my $featObj = Feature->new(dbh=>$dbh, 
				       feature_name=>$name);
	    if (!$featObj) { return -1;}
	    $self->{'_type'} = "Feature";
	    $self->{'_No'} = $featObj->feature_no;
        }
	else {
	    $self->{'_type'} = "Locus";
	    $self->{'_No'} = $locusObj->locus_no;
	}
    }
}

########################################################################
sub getReferenceList {
########################################################################
    my ($self) = @_;
	
    Reference->GetRefNo4pubmedHashRef(dbh=>$dbh,
		      ReferenceNo4PubmedRef=>\%ReferenceNo4Pubmed);
    
}


#########################################################################
sub checkGeneInfo {
#########################################################################
    my ($self, $refNo) = @_;
    my $sth;
    if ($self->{'_type'} =~ /Locus/i) {
	my $arrayRef = Locus_gene_info->GetTopicArrayRefBYrefNoLocusNo(
					      dbh=>$dbh,
					      reference_no=>$refNo,
					      locus_no=>$self->{'_No'});
	my @tag;
	foreach my $rowRef (@$arrayRef) {
	    my ($topic) = @$rowRef;
	    push(@tag, $topic);
	}
	if ($#tag < 0) {
	    $self->insertLocusGeneInfo($self->{'_No'}, $refNo);
	}
	return @tag;
    }
    else {
	my $arrayRef = Feat_gene_info->GetTopicArrayRefBYrefNoFeatNo(
					      dbh=>$dbh,
					      reference_no=>$refNo,
					      feature_no=>$self->{'_No'});
	my @tag;
	foreach my $rowRef (@$arrayRef) {
	    my ($topic) = @$rowRef;
	    push(@tag, $topic);
	}
	if ($#tag < 0) {
	    $self->insertFeatGeneInfo($self->{'_No'}, $refNo);
	}
	return @tag;
    }
}

#######################################################################
sub insertRefLink {
#######################################################################
    my ($self, $refNo, $No, $type) = @_;
    my $tabNm = uc($type);
    my $prikeyCol = "${type}_NO"; 
    eval { 
	Reflink->Insert(dbh=>$dbh,
			literals=>{reflink_no=>'CGM_DDB.reflinkno_seq.nextval'},
			binds=>{reference_no=>$refNo,
			        tab_name=>$tabNm,
			        primary_key=>$No,
			        primary_key_col=>$prikeyCol});
    };
    if ($@) {
	$dbh->rollback;
        return $@;
    }
    else {
        $dbh->commit;
        return 1;
    }
}


########################################################################
sub insertLocusGeneInfo {
########################################################################
    my ($self, $locusNo, $refNo, $topic) = @_;
    if (!$topic) { $topic = "Not yet curated"; } 
    eval {
	Locus_gene_info->Insert(dbh=>$dbh,
			        binds=>{locus_no=>$locusNo,
				        reference_no=>$refNo,
				        literature_topic=>$topic});
    };
    if ($@) {
	$dbh->rollback;
	return $@;
    }
    else {
	$dbh->commit;
	return 1;
    }
}

########################################################################
sub insertFeatGeneInfo {
########################################################################
    my ($self, $featNo, $refNo, $topic) = @_;
    if (!$topic) { $topic = "Not yet curated"; }
    eval {
	Feat_gene_info->Insert(dbh=>$dbh,
			       binds=>{feature_no=>$featNo,
				       reference_no=>$refNo,
				       literature_topic=>$topic});
    };
    if ($@) {
	$dbh->rollback;
	return $@;
    }
    else {
	$dbh->commit;
	return 1;
    }
}



########################################################################
sub printGeneName {
########################################################################
    
    my $feat = param('feat');

    my %typeLabels = ('Locus'=>'Locus or locus_no',
		      'Feature'=>'Feature or feature_no');
    my @typeValues = qw/Locus Feature/;
    my $defaultType = param('type');
    if ($defaultType) { $defaultType = "\u$defaultType"; }
    else { $defaultType = "Locus"; }

    print 
	table(Tr(td({BGCOLOR=>'#ACBDCC'}, 
		    popup_menu(-name=>'type',
			       -"values"=>\@typeValues,
			       -default=>$defaultType,
			       -labels=>\%typeLabels
			       )).      
		 td(textfield(-name=>'feat', 
			      -value=>"$feat", 
			      -size=>38)).
		 td(br).td(br))).br;
}


########################################################################
sub err_report {
########################################################################
    my ($self, $err) = @_;

    &printStartPage($self->database, $self->title, $self->help);	

    print b($err);
    
    &printEndPage;
    exit;
}

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





