package GO::Tool::XrefsTool; use strict; use lib 'go/scratch/tools'; use base 'GO::Tool::GenericGoTool'; ### Various modules required use Data::Dumper; use CGI::Carp qw(fatalsToBrowser); use GO::Object::Generic; use GO::Object::XrefAbbr; use GO::TestSet qw(dfv_test); use GO::Utilities qw(:all); use GO::GeneralPurposeParser; use URI::Escape; #use Utility::TSLParser; sub _specification { my $self = shift; return ( 'sort', { test => dfv_test('is_in_list_p', { list => ['abbreviation'], this => 1 } ), default => 'abbreviation', }, 'xref', { view_single => { test => qr/^.+$/, required => 1, allow_multiple => 1, }, }, 'page', { test => qr/^\d+$/, # must be a number default => '1', }, 'page_size', { test => qr/^(\d+|all)$/, # must be a number or all default => 'all', }, # rm => { # test => qr/^view_(all|single)$/, # default => sub { # my $dfvr = shift; # my $input = $dfvr->get_input_data( as_hashref => 1 ); # if ( exists $input->{xref}) # { return 'view_single'; } # else # { return 'view_all'; } # }, # dependencies => { # "view_single" => [ qw( xref ) ], # } # }, ); } ### stuff we're going to need ### xref db file my $xref_db = "/Users/gwg/go/doc/GO.xrf_abbs"; ### the cross-references master, official adder of xrefs to the GO.xrf_abbs db ### new cross-references will be sent by email to this address for checking my $xref_master = ""; sub setup { my $self = shift; $self->start_mode('view_all'); $self->mode_param(\&set_run_mode); $self->error_mode('die_and_output_error'); $self->run_modes( 'view_all' => 'view_all', 'view_single' => 'view_single', 'fatal_error' => 'die_and_output_error', 'AUTOLOAD' => 'view_all', ); } ## override the default just to speed things up #sub _runmode_specific_data { # my $self = shift; # return [ 'xref' ]; #} sub set_run_mode { my $self = shift; my %cgi_h = $self->query->Vars; return 'view_single' if exists $cgi_h{xref}; return 'view_all'; } # configure the template before we do anything else sub cgiapp_init { my $self = shift; $self->tt_config( TEMPLATE_OPTIONS => { INCLUDE_PATH=> [ qw( /Users/gwg/go/scratch/tools/templates/ /Users/gwg/go/www/) ], TRIM=>1, }, ); } ## stuff to do before we run the page-specific code sub cgiapp_prerun { my $self = shift; $self->startme; $self->debugme("current runmode: ". $self->get_current_runmode); # check the input query, replace dodgy params with the defaults my $results = $self->check_input_query({ replace_with_defaults => 1, spec_profile => $self->get_current_runmode }); if (!$results->success) { # set the mode to 'error' $self->prerun_mode('fatal_error'); # create an error message my $err_str; if ($self->get_current_runmode eq 'view_single' && ! $results->valid('xref') ) { if ($results->missing('xref')) { $err_str = 'You have not entered a query'; } elsif ($results->invalid('xref')) { $err_str = 'You have entered an invalid xref'; } } if (!$err_str) { $err_str = join "
", @{ GO::Utilities::summarize_errors($results) }; } $self->fatal_msg($err_str); } } sub view_single { my $self = shift; return $self->retrieve_data({ single => 1 }); } sub view_all { my $self = shift; return $self->retrieve_data; } =head2 retrieve_data Function to get data from the DB, either for a single xref or the whole lot. input: $self, optional flag which will trigger a search for an ID if present; otherwise, the operation will get all xrefs. =cut sub retrieve_data { my $self = shift; $self->startme; my $options = shift; my $output; # get the checked query my $query_h = $self->param('validated_query'); # get the parser ready for action my $parser_args = { file => $xref_db, file_separator => "\n\n", inner_parser => { parser => 'multi_field_tag_value', return_record_as_object => 'GO::Object::XrefAbbr', check_input => 1, filter_field => qr/^[^!]/, }, }; if ($options->{single}) # this is a single GO XREF query { # create the search query using the data in parsed query data # the param we need in the query is id # we should check alt_id too # in case we have more than one go ref, turn the query into a list $query_h->{xref} = [ $query_h->{xref} ] if ! ref($query_h->{xref}); # create the query # check for $query_h->{id} appearing as a go_ref_id or alt_id # ignore any record which doesn't feature $query_h->{id} somewhere $parser_args->{inner_parser}{filter_record} = [ map { qr/abbreviation: $_\b/i } @{$query_h->{xref}} ]; } # load the cross-references; dies if no cross-references present my $xref_arr = $self->get_data_from_file($parser_args); if (!$xref_arr || !@$xref_arr) { if ($options->{single}) { # query for one (or more) references my $msg; my $last = pop @{$query_h->{xref}}; if (scalar (@{$query_h->{xref}}) != 0) { $msg = "There are no GO references with the IDs " . join(", ", @{$query_h->{xref}}) . " or " . $last . ". Dying"; } else { $msg = "There is no GO reference with the ID " . $last . ". Dying"; } die $msg; } # if there's no data, die. $self->printerr("FATAL: No reference data found in $xref_db"); die "No valid data could be found. Please check $xref_db and try again. Dying"; } elsif ($options->{single} && scalar @$xref_arr != scalar @{$query_h->{xref}}) { # we have a mismatch between the number of refs we looked for and the number # we found. $self->debugme("Mismatch between refs sought and refs found: seeking ".scalar @{$query_h->{xref}}.", found ".scalar @$xref_arr); # some kind of matching thing here... } # get the sorted list my $sorted_list = GO::Utilities::sort_list({ list => $xref_arr, crit => [ $query_h->{'sort'} ] }); # $self->debugme("sorted_list: ".Dumper($sorted_list)); # get the subset of the results, if appropriate my $paged = get_results_chunk($sorted_list, { chunk_n => $query_h->{page}, chunk_size => $query_h->{page_size} }); $output->{xref_arr} = $paged->{subset}; $output->{n_pages} = $paged->{n_chunks}; $output->{page} = $paged->{chunk_n}; if (scalar @{$output->{xref_arr}} > 1) { $output->{'index'} = $self->create_index($output->{xref_arr}, $query_h->{'sort'}); } # set up all the other stuff and output the template return $self->tt_process('view_xref.tmpl', $self->set_up_output($output)) || die "Template toolkit messed up, the bastard!: ", $self->tt_obj->error(), "Dying"; } sub set_up_output { my $self = shift; $self->startme; my $tmpl_vars = shift || {}; # the checked query into $output $tmpl_vars->{query_h} = $self->param('validated_query'); $tmpl_vars = { %$tmpl_vars, base_url => 'http://127.0.0.1/cgi-bin/xrefs.cgi', install_dir => 'http://127.0.0.1/go/', }; if ($tmpl_vars->{n_pages} && $tmpl_vars->{n_pages} > 1) { ### set up URLs for paging, etc. my $url_h; my $spec = $self->get_spec; foreach my $p (keys %$spec) { # if the parameter is set AND there's no default or the parameter differs # from the default, add the param to the URL if ($tmpl_vars->{query_h}{$p} && (!$spec->{$p}{default} || # no default ($spec->{$p}{default} && # default, param differs from default $spec->{$p}{default} ne $tmpl_vars->{query_h}{$p}) ) ) { $url_h->{$p} = uri_escape($tmpl_vars->{query_h}{$p}); } } # paging URLs: need everything except page number delete $url_h->{page} if $url_h->{page}; $tmpl_vars->{url_for_paging} = join( "&", map { my $k = $_; if (ref($url_h->{$k}) eq 'ARRAY') { join( "&", map { $k . "=" . $_ } @{$url_h->{$k}} ); } else { $k . "=" . $url_h->{$k}; } } keys %$url_h ); $self->debugme("url for paging: ".Dumper($tmpl_vars->{url_for_paging})); } return $tmpl_vars; } 1;