[Bio] / Sprout / ResultHelper.pm Repository:
ViewVC logotype

Annotation of /Sprout/ResultHelper.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (view) (download) (as text)

1 : parrello 1.1 #!/usr/bin/perl -w
2 :    
3 :     package ResultHelper;
4 :    
5 :     use strict;
6 :     use Tracer;
7 :     use FIG;
8 :     use URI::Escape;
9 :    
10 :     =head1 Search Result Display Helper
11 :    
12 :     =head2 Introduction
13 :    
14 :     This is the base class for search output. It provides common methods for formatting the
15 :     output and providing options to the caller. This class is never used by itself.
16 :     Instead, a subclass (whose name begins with C<RH> is constructed.
17 :    
18 :     The following fields are maintained by this object.
19 :    
20 :     =over 4
21 :    
22 :     =item parent
23 :    
24 :     The parent search helper.
25 :    
26 :     =item record
27 :    
28 :     An B<ERDBObject> representing the current data.
29 :    
30 :     =item columns
31 :    
32 :     Reference to a hash specifying the different possible columns that can be
33 :     included in the result.
34 :    
35 :     =back
36 :    
37 :     Additional fields may be appended by the subclasses.
38 :    
39 :     =head2 Column Processing
40 :    
41 :     The subclass will generally have multiple column names defined. For each column,
42 :     several bits of information are needed-- how to format the column, how to compute
43 :     the column value at search time, how to compute it at run time (which is optional),
44 :     the column title to be used, and whether or not the column should be included in
45 :     a download. The orthodox object-oriented method for doing this would be to define
46 :     a B<Column> class and define each possible column using a subclass. To make things
47 :     a little less cumbersome, we instead define each column using a static method in
48 :     the subclass. The method gets as its parameters the result helper object and
49 :     the type of information required. For example, the following call would ask for
50 :     the title of a column called C<orgName>.
51 :    
52 :     my $title = RHFeatures::orgName(title => $rhelp);
53 :    
54 :     The B<orgName> method itself would look like this.
55 :    
56 :     sub orgName {
57 :     # Get the parameters.
58 :     my ($type, $rhelp, $key) = @_;
59 :     # Declare the return variable.
60 :     my $retVal;
61 :     # Process according to the information requested.
62 :     if ($type eq 'title' {
63 :     # Return the title for this column.
64 :     $retVal = 'Organism and Gene ID';
65 :     } elsif ($type eq 'download') {
66 :     # This field should be included in a download.
67 :     $retVal = 'text'; # or 'num', or 'list', or ''
68 :     } elsif ($type eq 'style') {
69 :     # This is a text field, so it's left-aligned.
70 :     $retVal = "leftAlign";
71 :     } elsif ($type eq 'value') {
72 :     # Get the organism and feature name.
73 :     $rhelp->FeatureName();
74 :     } elsif ($type eq 'runTimeValue') {
75 :     # This field does not require a runtime value.
76 :     };
77 :     return $retVal;
78 :     }
79 :    
80 :     The method is essentially a giant case statement based on the type of data desired. The
81 :     types are
82 :    
83 :     =over 4
84 :    
85 :     =item title
86 :    
87 :     Return the title of the column to be used when it is displayed.
88 :    
89 :     =item download
90 :    
91 :     Identifies how the column should be downloaded. An empty string means it should not
92 :     be downloaded at all. The other values are C<num>, indicating that the column contains
93 :     numeric data, C<text>, indicating that the column contains an html-escaped string,
94 : parrello 1.2 C<link>, indicating that the column contains a L</Formlet> or L</FakeButton>,
95 :     C<list>, indicating that the column contains a comma-separated list with optional
96 :     hyperlinks, or C<align>,indicating that the column contains multi-line
97 :     aligned text with individual lines separated by a C<br> tag.
98 : parrello 1.1
99 :     =item style
100 :    
101 :     Return the style to be used to display each table cell in the column. The return
102 :     value is a valid C<TD> class name from the style sheet. The style sheet should
103 :     contain styles for C<leftAlign>, C<rightAlign>, and C<center> to accomodate the
104 :     most common requirements.
105 :    
106 :     =item value
107 :    
108 :     Return the value to be stored in the result cache. In most cases, this should be an
109 :     html string. If the value is to be computed when the data is displayed (which is
110 :     sometimes necessary for performance reasons), then the return value should be of
111 :     the form C<%%>I<colName>C<=>I<key>, where I<colName> is the column name and
112 :     I<key> is a value used to compute the result at display time. The key value will
113 :     be passed as a third parameter to the column method.
114 :    
115 :     =item runTimeValue
116 :    
117 :     Return the value to be displayed. This method is only used when the information
118 :     is not easily available at the time the result cache is built.
119 :    
120 :     =back
121 :    
122 :     The idea behind this somewhat cumbersome design is that new columns can be added
123 :     very easily by simply adding a new method to the result helper.
124 :    
125 :     Note that a column name must be a valid PERL method name! This means no spaces
126 :     or other fancy stuff.
127 :    
128 :     Run-time values are a bit tricky, and require some explanation. The normal procedure
129 :     during a search is to compute the values to be displayed as soon as an item is found
130 :     and store them directly in the result cache. Run-time values are those that are too
131 :     expensive to compute during the search, so they are not computed until the result
132 :     cache is displayed. Because a search can return thousands of results, but only 50 or
133 :     so are displayed at a time, this makes a big difference.
134 :    
135 :     =head2 Extra Columns
136 :    
137 :     It is necessary for individual searches to be able to create output columns specific
138 :     to the type of search. These are called extra columns.
139 :    
140 :     To create extra columns, you use the L</AddExtraColumn> method. This method
141 :     specifies the location of an extra column in the column list, its name, and its format.
142 :    
143 :     The extra columns are put in whatever positions the user specifies, although if
144 :     you try to put two columns in the same place or add a column before another added
145 :     column, this could cause the position to shift.
146 :    
147 :     Unlike regular columns, there is no need to compute a value or run-time value. The
148 :     other column properties (title, style, etc.) are stored in the extra column's
149 :     definition in this object. When the column headers are written, the header for an
150 :     extra column is in the form C<X=>I<something>. The I<something> is a frozen copy
151 :     of the extra column's hash. When the headers are read back in, the extra column data
152 :     is thawed into the hash so that the various options are identical to what they were
153 :     when the result cache was created.
154 :    
155 :     Extra columns are the most volatile requirement in the whole search system. I will
156 :     count myself happy if this implementation of them lasts more than a week.
157 :    
158 :     =cut
159 :    
160 :     # This value is used to do a single indent level in the XML output.
161 :     use constant XML_INDENT => " ";
162 :    
163 :     =head2 Public Methods
164 :    
165 :     =head3 new
166 :    
167 : parrello 1.5 my $rhelp = ResultHelper->new($shelp);
168 : parrello 1.1
169 :     Construct a new ResultHelper object to serve the specified search helper.
170 :    
171 :     =over 4
172 :    
173 :     =item shelp
174 :    
175 :     Parent search helper that is generating the output.
176 :    
177 :     =item type
178 :    
179 :     Classname used to format requests for columns.
180 :    
181 :     =item extras
182 :    
183 :     Reference to a hash of extra column data keyed on extra column name. For each extra column,
184 :     it contains the column's current value.
185 :    
186 :     =item cache
187 :    
188 :     A hash for use by the run-time value methods, to save time when multiple run-time values
189 :     use the same base object.
190 :    
191 :     =item columns
192 :    
193 :     The list of the columns to displayed in the search results. Normal columns are stored as
194 :     strings. Extra columns are stored as hash references.
195 :    
196 :     =item record
197 :    
198 :     Data record for the current output row.
199 :    
200 :     =item id
201 :    
202 :     ID for the current output row.
203 :    
204 :     =item RETURN
205 :    
206 :     Returns a newly-constructed result helper.
207 :    
208 :     =back
209 :    
210 :     =cut
211 :    
212 :     sub new {
213 :     # Get the parameters.
214 :     my ($class, $shelp) = @_;
215 :     # Save the result type in the CGI parms.
216 :     my $cgi = $shelp->Q();
217 :     $cgi->param(-name => 'ResultType', -value => substr($class, 2));
218 :     Trace("Result helper created of type $class.") if T(3);
219 :     # Create the $rhelp object.
220 :     my $retVal = {
221 :     parent => $shelp,
222 :     record => undef,
223 :     id => undef,
224 :     type => $class,
225 :     extras => {},
226 :     cache => {},
227 :     columns => [],
228 :     };
229 :     # Return it.
230 :     return $retVal;
231 :     }
232 :    
233 :     =head3 DB
234 :    
235 : parrello 1.5 my $sprout = $rhelp->DB();
236 : parrello 1.1
237 :     Return the Sprout object for accessing the database.
238 :    
239 :     =cut
240 :    
241 :     sub DB {
242 :     # Get the parameters.
243 :     my ($self) = @_;
244 :     # Return the parent helper's database object.
245 :     return $self->Parent()->DB();
246 :     }
247 :    
248 :     =head3 PutData
249 :    
250 : parrello 1.5 $rhelp->PutData($sortKey, $id, $record);
251 : parrello 1.1
252 :     Store a line of data in the result file.
253 :    
254 :     =over 4
255 :    
256 :     =item sortKey
257 :    
258 :     String to be used for sorting this line of data among the others.
259 :    
260 :     =item id
261 :    
262 :     ID string for the result line. This is not shown in the results, but
263 :     is used by some of the download methods.
264 :    
265 :     =item record
266 :    
267 :     An B<ERDBObject> containing data to be used by the column methods.
268 :    
269 :     =back
270 :    
271 :     =cut
272 :    
273 :     sub PutData {
274 :     # Get the parameters.
275 :     my ($self, $sortKey, $id, $record) = @_;
276 :     # Save the data record and ID so the column methods can get to it.
277 :     $self->{record} = $record;
278 :     $self->{id} = $id;
279 :     # Loop through the columns, producing output data.
280 :     my @outputCols = ();
281 :     for my $column (@{$self->{columns}}) {
282 :     push @outputCols, $self->ColumnValue($column);
283 :     }
284 :     # Get the parent search helper.
285 :     my $shelp = $self->{parent};
286 :     # Write the column data.
287 :     $shelp->WriteColumnData($sortKey, $id, @outputCols);
288 :     }
289 :    
290 :     =head3 GetColumnHeaders
291 :    
292 : parrello 1.5 my $colHdrs = $rhelp->GetColumnHeaders();
293 : parrello 1.1
294 :     Return the list of column headers for this session. The return value is a
295 :     reference to the live column header list.
296 :    
297 :     =cut
298 :    
299 :     sub GetColumnHeaders {
300 :     # Get the parameters.
301 :     my ($self) = @_;
302 :     # Return the column headers.
303 :     return $self->{columns};
304 :     }
305 :    
306 :     =head3 DownloadFormatsAvailable
307 :    
308 : parrello 1.5 my %dlTypes = $rhelp->DownloadFormatsAvailable();
309 : parrello 1.1
310 :     Return a hash mapping each download type to a download description. The default is
311 :     the C<tbl> format, which is a tab-delimited download, and the C<xml> format,
312 :     which is XML. If you want additional formats, override L</MoreDownloadFormats>.
313 :    
314 :     =cut
315 :    
316 :     sub DownloadFormatsAvailable {
317 :     # Get the parameters.
318 :     my ($self) = @_;
319 :     Trace("Creating download type hash.") if T(3);
320 :     # Declare the return variable.
321 :     my %retVal = ( tbl => 'Results table as a tab-delimited file',
322 :     xml => 'Results table in XML format');
323 :     Trace("Asking for download formats from the helper.") if T(3);
324 :     # Ask for more formats.
325 :     $self->MoreDownloadFormats(\%retVal);
326 :     # Return the resulting hash.
327 :     return %retVal;
328 :     }
329 :    
330 :     =head3 DownloadDataLine
331 :    
332 : parrello 1.5 $rhelp->DownloadDataLine($objectID, $dlType, \@cols, \@colHdrs);
333 : parrello 1.1
334 :     Return one or more lines of download data. The exact data returned depends on the
335 : parrello 1.5 download type.
336 : parrello 1.1
337 :     =over 4
338 :    
339 :     =item objectID
340 :    
341 :     ID of the object whose data is in this line of results.
342 :    
343 :     =item dlType
344 :    
345 :     The type of download (e.g. C<tbl>, C<fasta>).
346 :    
347 :     =item eol
348 :    
349 :     The end-of-line character to use.
350 :    
351 :     =item cols
352 :    
353 :     A reference to a list of the data columns, or a string containing
354 :     C<header> or C<footer>. The strings will cause the header lines
355 :     or footer lines to be output rather than a data line.
356 :    
357 :     =item colHdrs
358 :    
359 :     A reference to a list of the column headers. Each header describes the data found
360 :     in the corresponding column of the I<cols> list.
361 :    
362 :     =item RETURN
363 :    
364 :     Returns a list of strings that can be written to the download output.
365 :    
366 :     =back
367 :    
368 :     =cut
369 :    
370 :     sub DownloadDataLine {
371 :     # Get the parameters.
372 :     my ($self, $objectID, $dlType, $cols, $colHdrs) = @_;
373 :     # Declare the return variable.
374 :     my @retVal = ();
375 :     # Check the download type.
376 :     if ($dlType eq 'tbl' || $dlType eq 'xml') {
377 :     # Check for headers or footers.
378 :     if ($cols eq 'header') {
379 :     # Here we want headers. Only the XML type has them.
380 :     if ($dlType eq 'xml') {
381 :     @retVal = ('<?xml version="1.0" encoding="utf-8" ?>',
382 :     '<Results>');
383 :     }
384 :     } elsif ($cols eq 'footer') {
385 :     # Here we want footers. Again, only the XML type requires them.
386 :     if ($dlType eq 'xml') {
387 :     @retVal = ('</Results>');
388 :     }
389 :     } else {
390 :     # Here we are downloading the displayed columns as a tab-delimited file or
391 :     # as XML and we are tasked with producing the output lines for the current
392 :     # row of data. The first thing is to get the download format information
393 :     # about the columns.
394 :     my @keepCols = map { $self->ColumnDownload($_) } @{$colHdrs};
395 :     # Remove the columns that are not being kept. The list we create here
396 :     # will contain the name of each column, its value, and its download format.
397 :     my @actualCols = ();
398 :     for (my $i = 0; $i <= $#keepCols; $i++) {
399 : parrello 1.3 Trace("Keep flag for $i is $keepCols[$i].") if T(4);
400 : parrello 1.1 if ($keepCols[$i]) {
401 :     push @actualCols, [$colHdrs->[$i], $self->GetRunTimeValues($cols->[$i]), $keepCols[$i]];
402 :     }
403 :     }
404 : parrello 1.3 Trace(scalar(@actualCols) . " columns kept.") if T(4);
405 : parrello 1.1 # Now it's time to do the actual writing, so we need to know if this
406 :     # is XML or tab-delimited.
407 :     if ($dlType eq 'tbl') {
408 :     # Clean up the HTML.
409 :     my @actual = map { HtmlCleanup($_->[1], $_->[2]) } @actualCols;
410 :     # Return the line of data.
411 :     push @retVal, join("\t", @actual);
412 : parrello 1.3 Trace("Output line is\n" . join("\n", @actual)) if T(4);
413 : parrello 1.1 } elsif ($dlType eq 'xml') {
414 : parrello 1.3 # Convert to XML.
415 :     my @actual = ();
416 :     for my $actualCol (@actualCols) {
417 :     # First we need the column name. This is the column header for an ordinary column,
418 :     # and the title for an extra column.
419 :     my $colName;
420 :     if (ref $actualCol->[0]) {
421 :     # Here we have an extra column.
422 :     $colName = $actualCol->[0]->{title};
423 :     # Remove internal spaces to make it name-like.
424 :     $colName =~ s/\s+//g;
425 :     } else {
426 :     # For a normal column, the value is the name.
427 :     $colName = $actualCol->[0];
428 :     }
429 :     # Create the tag for this column. Since a single XML tag can contain multiple
430 :     # lines, we re-split them. This is important, because when the lines are output
431 :     # we need to insure the correct EOL character is used.
432 :     push @actual, split /\n/, "<$colName>" . XmlCleanup($actualCol->[1], $actualCol->[2]) . "</$colName>";
433 :     }
434 : parrello 1.1 # Return the XML object.
435 :     push @retVal, XML_INDENT x 1 . "<Item id=\"$objectID\">";
436 :     push @retVal, map { XML_INDENT x 2 . $_ } @actual;
437 :     push @retVal, XML_INDENT x 1 . "</Item>";
438 :     }
439 :     }
440 :     } else {
441 :     # Now we have a special-purpose download format, so we let the subclass deal
442 :     # with it.
443 :     @retVal = $self->MoreDownloadDataMethods($objectID, $dlType, $cols, $colHdrs);
444 :     }
445 :     # Return the result.
446 :     return @retVal;
447 :     }
448 :    
449 :     =head3 Formlet
450 :    
451 : parrello 1.5 my $html = $rhelp->Formlet($caption, $url, $target, %parms);
452 : parrello 1.1
453 :     Create a mini-form that posts to the specified URL with the specified parameters. The
454 :     parameters will be stored in hidden fields, and the form's only visible control will
455 :     be a submit button with the specified caption.
456 :    
457 :     Note that we don't use B<CGI.pm> services here because they generate forms with extra characters
458 :     and tags that we don't want to deal with.
459 :    
460 :     This method is tightly bound to L</FormletToLink>, which converts a formlet to a URL. A
461 :     change here will require a change to the other method.
462 :    
463 :     =over 4
464 :    
465 :     =item caption
466 :    
467 :     Caption to be put on the form button.
468 :    
469 :     =item url
470 :    
471 :     URL to be put in the form's action parameter.
472 :    
473 :     =item target
474 :    
475 :     Frame or target in which the form results should appear. If C<undef> is specified,
476 :     the default target will be used.
477 :    
478 :     =item parms
479 :    
480 :     Hash containing the parameter names as keys and the parameter values as values.
481 :    
482 :     =back
483 :    
484 :     =cut
485 :    
486 :     sub Formlet {
487 :     # Get the parameters.
488 :     my ($self, $caption, $url, $target, %parms) = @_;
489 :     # Compute the target HTML.
490 :     my $targetHtml = ($target ? " target=\"$target\"" : "");
491 :     # Start the form.
492 :     my $retVal = "<form method=\"POST\" action=\"$url\"$target>";
493 :     # Add the parameters.
494 :     for my $parm (keys %parms) {
495 :     $retVal .= "<input type=\"hidden\" name=\"$parm\" value=\"$parms{$parm}\" />";
496 :     }
497 :     # Put in the button.
498 :     $retVal .= "<input type=\"submit\" name=\"submit\" value=\"$caption\" class=\"button\" />";
499 :     # Close the form.
500 :     $retVal .= "</form>";
501 :     # Return the result.
502 :     return $retVal;
503 :     }
504 :    
505 :     =head3 HtmlCleanup
506 :    
507 : parrello 1.5 my $text = ResultHelper::HtmlCleanup($htmlText, $type);
508 : parrello 1.1
509 :     Take a string of Html text and clean it up so it appears as real text.
510 :     Note that this method is not yet sophisticated enough to detect right-angle brackets
511 :     inside tag parameters, nor can it handle style or script tags. Its only sophistication
512 : parrello 1.2 is that it knows how to convert formlets or fake buttons URLs. Otherwise, it is a dirt simple
513 : parrello 1.1 method that suffices for search result processing.
514 :    
515 :     =over 4
516 :    
517 :     =item htmlText
518 :    
519 :     Html text to clean up.
520 :    
521 :     =item type
522 :    
523 :     Type of column: C<num> for a number, C<text> for a string, C<list> for a
524 :     comma-separated list, and C<link> for a formlet link.
525 :    
526 :     =item RETURN
527 :    
528 :     Returns the downloadable form of the Html string.
529 :    
530 :     =back
531 :    
532 :     =cut
533 :    
534 :     sub HtmlCleanup {
535 :     # Get the parameters.
536 :     my ($htmlText, $type) = @_;
537 :     # Declare the return variable.
538 :     my $retVal;
539 :     # Check for a formlet.
540 :     if ($type eq 'link') {
541 : parrello 1.2 # Here we have a formlet or fake button and we want to convert it to a URL.
542 :     $retVal = ButtonToLink($htmlText);
543 : parrello 1.1 } elsif ($type eq 'align') {
544 :     # Here we have multiple lines. Convert the new-lines to serial commas.
545 : parrello 1.3 $retVal = $htmlText;
546 : parrello 1.1 $retVal =~ s/<br\s*\/?>/, /g;
547 : parrello 1.4 # Convert &nbsp; marks to real spaces.
548 :     $retVal =~ s/&nbsp;/ /g;
549 : parrello 1.1 } else {
550 :     # Here we have normal HTML. Start by taking the raw text.
551 :     $retVal = $htmlText;
552 :     # Delete any tags. This is a very simplistic algorithm that will fail if there
553 :     # is a right angle bracket inside a parameter string.
554 :     $retVal =~ s/<[^>]+>//g;
555 : parrello 1.3 # Convert &nbsp; marks to real spaces.
556 :     $retVal =~ s/&nbsp;/ /g;
557 : parrello 1.1 # Unescape the & tags.
558 :     $retVal = CGI::unescapeHTML($retVal);
559 :     }
560 :     # Return the result.
561 :     return $retVal;
562 :     }
563 :    
564 :     =head3 XmlCleanup
565 :    
566 : parrello 1.5 my $text = ResultHelper::XmlCleanup($htmlText, $type);
567 : parrello 1.1
568 :     Take a string of Html text and clean it up so it appears as html.
569 :    
570 :     =over 4
571 :    
572 :     =item htmlText
573 :    
574 :     Html text to clean up.
575 :    
576 :     =item type
577 :    
578 :     Type of column: C<num> for a number, C<text> for a string, C<list> for a
579 : parrello 1.2 comma-separated list, and C<link> for a formlet or fake button.
580 : parrello 1.1
581 :     =item RETURN
582 :    
583 :     Returns the column data in XML format.
584 :    
585 :     =back
586 :    
587 :     =cut
588 :    
589 :     sub XmlCleanup {
590 :     # Get the parameters.
591 :     my ($htmlText, $type) = @_;
592 :     # Declare the return variable.
593 :     my $retVal;
594 :     # Check for a formlet.
595 :     if ($type eq 'link') {
596 : parrello 1.2 # Here we have a formlet or fake button and we want to convert it to a URL.
597 :     $retVal = ButtonToLink($htmlText);
598 : parrello 1.1 } elsif ($type eq 'num' || $type eq 'text') {
599 :     # Here we have a number or text. Return the raw value.
600 :     $retVal = $htmlText;
601 :     } elsif ($type eq 'align') {
602 :     # Here we have aligned text. This is converted into an XML array of lines.
603 :     # First, we find the break tags.
604 : parrello 1.3 Trace("Alignment cleanup of: $htmlText") if T(4);
605 : parrello 1.1 my @lines = split /<br[^>]+>/, $htmlText;
606 : parrello 1.3 Trace(scalar(@lines) . " lines found.") if T(4);
607 : parrello 1.1 # Format the lines as an XML array. The extra new-line causes the first array
608 :     # element to be on a separate line from the first item tag.
609 : parrello 1.3 $retVal = "\n" . join("", map { XML_INDENT . "<line>$_</line>\n" } @lines);
610 : parrello 1.1 } elsif ($type eq 'list') {
611 :     # Here we have a comma-delimited list of possibly-linked strings. We will convert it to
612 :     # an XML array. First, we get the pieces.
613 :     my @entries = split /\s*,\s*/, $htmlText;
614 :     # Each piece is processed individually, so we can check for hyperlinks.
615 :     # The return value starts with a new-line, so that the first list element
616 :     # is not on the same line as the open tag.
617 :     $retVal = "\n";
618 :     for my $entry (@entries) {
619 :     # Check for a hyperlink.
620 :     if ($entry =~ /<a[^>]+(href="[^"]+")[^>]*>(.+)<\/a>/) {
621 :     # Put the URL in the tag.
622 :     $retVal .= XML_INDENT . "<value $1>$2</value>\n";
623 :     } else {
624 :     # No URL, so the tag is unadorned.
625 :     $retVal .= XML_INDENT . "<value>$entry</value>\n";
626 :     }
627 :     }
628 :     }
629 :     # Return the result.
630 :     return $retVal;
631 :     }
632 :    
633 : parrello 1.2 =head3 ButtonToLink
634 : parrello 1.1
635 : parrello 1.5 my $url = ResultHelper::ButtonToLink($htmlText);
636 : parrello 1.1
637 : parrello 1.2 Convert a formlet or fake button to a link. This process is bound very tightly with
638 :     the way L</Formlet> and L</FakeButton> generate Html. A change there requires a
639 :     change here.
640 : parrello 1.1
641 :     =over 4
642 :    
643 :     =item htmlText
644 :    
645 :     HTML text for the formlet.
646 :    
647 :     =item RETURN
648 :    
649 :     Returns a URL that will produce the same result as clicking the formlet button.
650 :    
651 :     =back
652 :    
653 :     =cut
654 :    
655 : parrello 1.2 sub ButtonToLink {
656 : parrello 1.1 # Get the parameters.
657 :     my ($htmlText) = @_;
658 :     # Declare the return variable.
659 :     my $retVal;
660 :     # We begin with the action.
661 : parrello 1.2 if ($htmlText =~ /action="([^"]+)"/i) {
662 :     # Action found, so this is a formlet. The action is the base of the URL.
663 :     $retVal = $1;
664 :     # Now, parse out the parameters, all of which are stored in the formlet as hidden
665 :     # input fields. This is the point where we assume that the formlet generates things
666 :     # in a well-defined format.
667 :     my @parms = ();
668 :     while ($htmlText =~ /<input\s+type="hidden"\s+name="([^"]+)"\s+value="([^"]+)"/ig) {
669 :     push @parms, "$1=" . uri_escape($2);
670 :     }
671 :     # If there were any parameters, assemble them into the URL.
672 :     if (scalar(@parms)) {
673 :     $retVal .= "?" . join(";", @parms);
674 :     }
675 :     } elsif ($htmlText =~ /<a\s+href="([^"]+)"/) {
676 :     # Here we have a fake button. The URL is the HREF.
677 :     $retVal = $1;
678 :     } else {
679 :     # Here the column is empty. We output an empty string.
680 :     $retVal = '';
681 : parrello 1.1 }
682 : parrello 1.2 # Now a final cleanup. If we have a URL and it's relative, we need to add our path to it.
683 :     if ($retVal && $retVal !~ m#http://#) {
684 :     # The link doesn't begin with http, so we must fix it. Get our URL.
685 :     my $cgi = CGI->new();
686 :     my $selfURL = $cgi->url(-full => 1);
687 :     # Strip off the page name.
688 :     $selfURL =~ m#^(.+)/[^/]+$#;
689 :     my $path = $1;
690 :     # Combine it with the relative URL.
691 :     $retVal = "$1/$retVal";
692 : parrello 1.1 }
693 :     # Return the result.
694 :     return $retVal;
695 :     }
696 :    
697 :     =head3 FakeButton
698 :    
699 : parrello 1.5 my $html = $rhelp->FakeButton($caption, $url, $target, %parms);
700 : parrello 1.1
701 :     Create a fake button that hyperlinks to the specified URL with the specified parameters.
702 :     Unlike a real button, this one won't visibly click, but it will take the user to the
703 :     correct place.
704 :    
705 :     The parameters of this method are deliberately identical to L</Formlet> so that we
706 :     can switch easily from real buttons to fake ones in the code.
707 :    
708 :     =over 4
709 :    
710 :     =item caption
711 :    
712 :     Caption to be put on the button.
713 :    
714 :     =item url
715 :    
716 :     URL for the target page or script.
717 :    
718 :     =item target
719 :    
720 :     Frame or target in which the new page should appear. If C<undef> is specified,
721 :     the default target will be used.
722 :    
723 :     =item parms
724 :    
725 :     Hash containing the parameter names as keys and the parameter values as values.
726 :     These will be appended to the URL.
727 :    
728 :     =back
729 :    
730 :     =cut
731 :    
732 :     sub FakeButton {
733 :     # Get the parameters.
734 :     my ($self, $caption, $url, $target, %parms) = @_;
735 :     # Declare the return variable.
736 :     my $retVal;
737 :     # Compute the target URL.
738 :     my $targetUrl = "$url?" . join(";", map { "$_=" . uri_escape($parms{$_}) } keys %parms);
739 :     # Compute the target-frame HTML.
740 :     my $targetHtml = ($target ? " target=\"$target\"" : "");
741 :     # Assemble the result.
742 :     return "<a href=\"$targetUrl\" $targetHtml><div class=\"button2 button\">$caption</div></a>";
743 :     }
744 :    
745 :     =head3 Parent
746 :    
747 : parrello 1.5 my $shelp = $rhelp->Parent();
748 : parrello 1.1
749 :     Return this helper's parent search helper.
750 :    
751 :     =cut
752 :    
753 :     sub Parent {
754 :     # Get the parameters.
755 :     my ($self) = @_;
756 :     # Return the parent.
757 :     return $self->{parent};
758 :     }
759 :    
760 :     =head3 Record
761 :    
762 : parrello 1.5 my $erdbObject = $rhelp->Record();
763 : parrello 1.1
764 :     Return the record currently stored in this object. The record contains the data for
765 :     the result output line being built, and is in the form of a B<ERDBObject>.
766 :    
767 :     =cut
768 :    
769 :     sub Record {
770 :     # Get the parameters.
771 :     my ($self) = @_;
772 :     # Get the record.
773 :     my $retVal = $self->{record};
774 :     # If it does not exist, trace a message.
775 :     Trace("No record found in result helper.") if T(3) && ! defined($retVal);
776 :     # Return the record.
777 :     return $retVal;
778 :     }
779 :    
780 :     =head3 ID
781 :    
782 : parrello 1.5 my $id = $rhelp->ID();
783 : parrello 1.1
784 :     Return the ID for the record currently stored in this object (if any).
785 :    
786 :    
787 :     =cut
788 :    
789 :     sub ID {
790 :     # Get the parameters.
791 :     my ($self) = @_;
792 :     # Get the record.
793 :     my $retVal = $self->{id};
794 :     # If it does not exist, trace a message. We say "no record found" because a
795 :     # missing ID implies a missing record.
796 :     Trace("No record found in result helper.") if T(3) && ! defined($retVal);
797 :     # Return the ID.
798 :     return $retVal;
799 :     }
800 :    
801 :    
802 :    
803 :     =head3 Cache
804 :    
805 : parrello 1.5 my $cacheHash = $rhelp->Cache();
806 : parrello 1.1
807 :     Return a reference to the internal cache. The internal cache is used by the
808 :     run-time value methods to keep stuff in memory between calls for the same
809 :     output line.
810 :    
811 :     =cut
812 :    
813 :     sub Cache {
814 :     # Get the parameters.
815 :     my ($self) = @_;
816 :     # Return the cache.
817 :     return $self->{cache};
818 :     }
819 :    
820 :     =head3 PreferredID
821 :    
822 : parrello 1.5 my $featureID = $rhelp->PreferredID($featureObject);
823 : parrello 1.1
824 :     Return the preferred ID for the specified feature. The feature passed in must be in the
825 :     form of an ERDB feature object. The preferred alias type will be determined using the
826 :     CGI C<AliasType> parameter, and then cached in the feature object using the name
827 :     C<Feature(alias)> so this method can find it easily if it is needed again.
828 :    
829 :     =over 4
830 :    
831 :     =item featureObject
832 :    
833 :     An B<ERDBObject> for the relevant feature.
834 :    
835 :     =item RETURN
836 :    
837 :     The preferred ID for the feature (Locus Tag, Uniprot ID, etc.) if one exists, otherwise
838 :     the FIG ID.
839 :    
840 :     =back
841 :    
842 :     =cut
843 :    
844 :     sub PreferredID {
845 :     # Get the parameters.
846 :     my ($self, $featureObject) = @_;
847 :     # Declare the return variable.
848 :     my $retVal;
849 :     # Check for a cached value.
850 :     if ($featureObject->HasField('Feature(alias)')) {
851 :     $retVal = $featureObject->PrimaryValue('Feature(alias)');
852 :     } else {
853 :     # Here we need to compute the alias. First, get the preferred type.
854 :     my $aliasType = $self->Parent()->GetPreferredAliasType();
855 :     # The fallback is to use the FIG ID.
856 :     my $fid = $featureObject->PrimaryValue('Feature(id)');
857 :     $retVal = $fid;
858 :     # We only need to proceed if the preferred type is NOT FIG.
859 :     if ($aliasType ne 'FIG') {
860 :     # Here we need to find a real alias of the specified type. To start,
861 :     # we need a Sprout object.
862 :     my $sprout = $self->DB();
863 :     # Ask for all the aliases connected to this feature ID.
864 :     my @aliases = $sprout->GetFlat(['IsAliasOf'], 'IsAliasOf(to-link) = ?',
865 :     [$fid], 'IsAliasOf(from-link)');
866 :     # Extract an alias of the preferred type.
867 :     my $foundAlias = AliasAnalysis::Find($aliasType, \@aliases);
868 :     # If an alias was found, use it. Otherwise, the FIG ID will stay in place.
869 :     if (defined($foundAlias)) {
870 :     $retVal = $foundAlias;
871 :     }
872 :     }
873 :     # Save the alias type for future calls.
874 :     $featureObject->AddValues('Feature(alias)', $retVal);
875 :     }
876 :     # Return the ID computed.
877 :     return $retVal;
878 :     }
879 :    
880 :    
881 :     =head2 Column-Related Methods
882 :    
883 :     =head3 Compute
884 :    
885 : parrello 1.5 my $retVal = $rhelp->Compute($type, $colName, $runTimeKey);
886 : parrello 1.1
887 :     Call a column method to return a result. This involves some fancy C<eval> stuff.
888 :     The column method is called as a static method of the relevant subclass.
889 :    
890 :     =over 4
891 :    
892 :     =item type
893 :    
894 :     The type of column data requested: C<title> for the column title, C<style> for the
895 :     column's display style, C<value> for the value to be put in the result cache,
896 :     C<download> for the indicator of how the column should be included in
897 :     downloads, and C<runTimeValue> for the value to be used when the result is
898 :     displayed. Note that if a run-time value is required, then the normal value
899 :     must be formatted in a special way (see L<Column Processing>).
900 :    
901 :     A little fancy dancing is required for extra columns. For extra columns, only
902 : parrello 1.5 the title, style, and download status are ever requested.
903 : parrello 1.1
904 :     =item colName
905 :    
906 :     Name of the column of interest. The name may contain a colon, in which case
907 :     the column name is the part before the colon and the value after it is
908 :     passed to the column method as the run-time key.
909 :    
910 :     =item runTimeKey (optional)
911 :    
912 :     If a run-time value is desired, this should be the key taken from the value stored
913 :     in the result cache.
914 :    
915 :     =item RETURN
916 :    
917 :     Returns the desired result for the specified column.
918 :    
919 :     =back
920 :    
921 :     =cut
922 :    
923 :     sub Compute {
924 :     # Get the parameters.
925 :     my ($self, $type, $colName, $runTimeKey) = @_;
926 :     # Declare the return variable.
927 :     my $retVal;
928 :     # Check for an extra column.
929 :     if (ref $colName eq 'HASH') {
930 :     # Look for the appropriate data from the hash.
931 :     if ($type eq 'value') {
932 :     # The caller wants the column value, which is stored in the "extras"
933 :     # member keyed by column name.
934 :     my $realName = $colName->{name};
935 :     $retVal = $self->{extras}->{$realName};
936 :     Trace("Extra column $realName retrieved value is $retVal.") if T(4);
937 :     } else {
938 :     # The other data items are stored in the column name itself.
939 :     $retVal = $colName->{$type};
940 :     }
941 :     } else {
942 :     # Here we have a real built-in column. The search helper chooses which of
943 :     # these to use (usually by adding to a default list), and we use static
944 :     # methods in our subclass to process them. An eval call is used to
945 :     # accomplish the result. First, we do some goofiness so we can deal
946 :     # with the possible absence of a run-time key.
947 :     my $realRunTimeKey = (defined $runTimeKey ? ", '$runTimeKey'" : "");
948 :     # Check for a complex column name. Note that during run-time expansion, the
949 :     # column names will have been simplified (that is, the colon will have been
950 :     # removed and the parameter attached to the incoming run-time key.
951 :     if ($colName =~ /(\S+):(.+)/) {
952 :     $colName = $1;
953 : parrello 1.3 $realRunTimeKey = ", '$2'";
954 : parrello 1.1 }
955 :     # Get the result helper type.
956 :     my $rhType = $self->{type};
957 :     # Create the string for returning the desired results.
958 :     my $expression = "${rhType}::$colName($type => \$self$realRunTimeKey)";
959 :     # Evaluate to get the result. Note we automatically translate undefined results to
960 :     # an empty string.
961 :     Trace("Evaluating: $expression") if T(4);
962 :     $retVal = eval($expression) || "";
963 :     # Check for an error.
964 :     if ($@) {
965 :     Trace("Evaluation failed in Compute of $expression") if T(1);
966 :     Confess("$self->{type} column request failed: $@");
967 :     }
968 :     }
969 :     # Return the computed result.
970 :     return $retVal;
971 :     }
972 :    
973 :     =head3 ColumnDownload
974 :    
975 : parrello 1.5 my $flag = $rhelp->ColumnDownload($colName);
976 : parrello 1.1
977 :     Return the type of data in the column, or an empty string if it should
978 :     not be downloaded. In general, all columns are downloaded except those
979 :     that are graphic representations of something.
980 :    
981 :     =over 4
982 :    
983 :     =item colName
984 :    
985 :     Name of the column in question.
986 :    
987 :     =item RETURN
988 :    
989 :     Returns one of the download data types discussed in L</Column Processing>.
990 :    
991 :     =back
992 :    
993 :     =cut
994 :    
995 :     sub ColumnDownload {
996 :     # Get the parameters.
997 :     my ($self, $colName) = @_;
998 :     # Compute the result.
999 :     my $retVal = $self->Compute(download => $colName);
1000 :     # Return it.
1001 :     return $retVal;
1002 :     }
1003 :    
1004 :     =head3 ColumnTitle
1005 :    
1006 : parrello 1.5 my $titleHtml = $rhelp->ColumnTitle($colName);
1007 : parrello 1.1
1008 :     Return the title to be used in the result table for the specified column.
1009 :    
1010 :     =over 4
1011 :    
1012 :     =item colName
1013 :    
1014 :     Name of the relevant column.
1015 :    
1016 :     =item RETURN
1017 :    
1018 :     Returns the html to be used for the column title.
1019 :    
1020 :     =back
1021 :    
1022 :     =cut
1023 :    
1024 :     sub ColumnTitle {
1025 :     # Get the parameters.
1026 :     my ($self, $colName) = @_;
1027 :     # Compute the result.
1028 :     my $retVal = $self->Compute(title => $colName);
1029 :     # Return it.
1030 :     return $retVal;
1031 :     }
1032 :    
1033 :     =head3 ColumnValue
1034 :    
1035 : parrello 1.5 my $htmlValue = $rhelp->ColumnValue($colName);
1036 : parrello 1.1
1037 :     Return the display value for a column. This could be HTML text or it
1038 :     could be a run-time value specification. The column value is computed
1039 :     using the data record currently stored in the result helper.
1040 :    
1041 :     =over 4
1042 :    
1043 :     =item colName
1044 :    
1045 :     Name of the column whose value is desired.
1046 :    
1047 :     =item RETURN
1048 :    
1049 :     Returns the value to be stored in the result cache.
1050 :    
1051 :     =back
1052 :    
1053 :     =cut
1054 :    
1055 :     sub ColumnValue {
1056 :     # Get the parameters.
1057 :     my ($self, $colName) = @_;
1058 :     # Compute the return value.
1059 :     my $retVal = $self->Compute(value => $colName);
1060 :     # Return it.
1061 :     return $retVal;
1062 :     }
1063 :    
1064 :     =head3 ColumnStyle
1065 :    
1066 : parrello 1.5 my $className = $rhelp->ColumnStyle($colName);
1067 : parrello 1.1
1068 :     Return the display style for the specified column. This must be a classname
1069 :     defined for C<TD> tags in the active style sheet.
1070 :    
1071 :     =over 4
1072 :    
1073 :     =item colName
1074 :    
1075 :     Name of the relevant column.
1076 :    
1077 :     =item RETURN
1078 :    
1079 :     Returns the name of the style class to be used for this column's cells.
1080 :    
1081 :     =back
1082 :    
1083 :     =cut
1084 :    
1085 :     sub ColumnStyle {
1086 :     # Get the parameters.
1087 :     my ($self, $colName) = @_;
1088 :     # Compute the return value.
1089 :     my $retVal = $self->Compute(style => $colName);
1090 :     # Return it.
1091 :     return $retVal;
1092 :     }
1093 :    
1094 :     =head3 GetRunTimeValues
1095 :    
1096 : parrello 1.5 my @valueHtml = $rhelp->GetRunTimeValues(@cols);
1097 : parrello 1.1
1098 :     Return the run-time values of a row of columns. The incoming values contain
1099 :     the actual column contents. Run-time columns will be identified by the
1100 :     leading C<%%> marker. The run-time columns are converted in sequence
1101 :     using methods in the base class.
1102 :    
1103 :     =over 4
1104 :    
1105 :     =item cols
1106 :    
1107 :     A list of columns. Runtime columns will be of the format C<%%>I<colName>C<=>I<key>,
1108 :     where I<colName> is the actual column name and I<key> is the key to be passed to
1109 :     the evaluator. Columns that do not have this format are unchanged.
1110 :    
1111 :     =item RETURN
1112 :    
1113 :     Returns a list of the final values for all the run-time columns.
1114 :    
1115 :     =back
1116 :    
1117 :     =cut
1118 :    
1119 :     sub GetRunTimeValues {
1120 :     # Get the parameters.
1121 :     my ($self, @cols) = @_;
1122 :     # Declare the return value.
1123 :     my @retVal = ();
1124 :     # Clear the cache. The run-time value methods can store stuff
1125 :     # in here to save computation time.
1126 :     $self->{cache} = {};
1127 :     # Loop through the columns.
1128 :     for my $col (@cols) {
1129 :     # Declare a holding variable.
1130 :     my $retVal;
1131 :     # Parse the column data.
1132 :     if ($col =~ /^%%(\w+)=(.+)/) {
1133 :     # It parsed as a run-time value, so call the Compute method.
1134 :     $retVal = $self->Compute(runTimeValue => $1, $2);
1135 :     } else {
1136 :     # Here it's a search-time value, so we leave it unchanged.
1137 :     $retVal = $col;
1138 :     }
1139 :     # Add this column to the result list.
1140 :     push @retVal, $retVal;
1141 :     }
1142 :     # Return the result.
1143 :     return @retVal;
1144 :     }
1145 :    
1146 :     =head3 SetColumns
1147 :    
1148 : parrello 1.5 $rhelp->SetColumns(@cols);
1149 : parrello 1.1
1150 :     Store the specified object columns. These are the columns computed by the search
1151 :     framework, and should generally be specified first. If the search itself is
1152 :     going to generate additional data, the columns for displaying this additional
1153 :     data should be specified by a subsequent call to L</AddExtraColumn>.
1154 :    
1155 :     =over 4
1156 :    
1157 :     =item cols
1158 :    
1159 :     A list of column names. These must correspond to names defined in the result
1160 :     helper subclass (see L</Column Processing>).
1161 :    
1162 :     =back
1163 :    
1164 :     =cut
1165 :    
1166 :     sub SetColumns {
1167 :     # Get the parameters.
1168 :     my ($self, @cols) = @_;
1169 :     # Store the columns in the column list. Note that this erases any
1170 :     # previous column information.
1171 :     $self->{columns} = \@cols;
1172 :     }
1173 :    
1174 :     =head3 AddExtraColumn
1175 :    
1176 : parrello 1.5 $rhelp->AddExtraColumn($name => $loc, %data);
1177 : parrello 1.1
1178 :     Add an extra column to the column list at a specified location.
1179 :    
1180 :     =over 4
1181 :    
1182 :     =item name
1183 :    
1184 :     The name of the column to add.
1185 :    
1186 :     =item loc
1187 :    
1188 :     The location at which the column should be displayed. The column is added
1189 :     at the specified column location in the column list. It may be moved,
1190 :     however, if subsequent column additions are placed at or before its
1191 :     specified location. To put a column at the beginning, specify C<0>;
1192 :     to put it at the end specify C<undef>.
1193 :    
1194 :     =item data
1195 :    
1196 :     A hash specifying the title, style, and download flag for the extra
1197 :     column. The download flag (key C<download>) should specify the type
1198 :     of data in the column. The title (key C<title>) should be the name
1199 :     displayed for the column in the result display table. The style
1200 :     (key C<style>) should be the style class used for displaying the cells
1201 :     in the column.
1202 :    
1203 :     =back
1204 :    
1205 :     =cut
1206 :    
1207 :     sub AddExtraColumn {
1208 :     # Get the parameters.
1209 :     my ($self, $name, $loc, %data) = @_;
1210 :     # Add the name to the column hash.
1211 :     $data{name} = $name;
1212 :     # Store the result in the column list.
1213 :     $self->_StoreColumnSpec(\%data, $loc);
1214 :     }
1215 :    
1216 :     =head3 AddOptionalColumn
1217 :    
1218 : parrello 1.5 $rhelp->AddOptionalColumn($name => $loc);
1219 : parrello 1.1
1220 :     Store the specified column name in the column list at the
1221 :     specified location. The column name must be one that
1222 :     is known to the result helper subclass. This method
1223 :     allows ordinary columns (as opposed to extra columns)
1224 :     to be added after the initial L</SetColumns> call.
1225 :    
1226 :     =over 4
1227 :    
1228 :     =item name
1229 :    
1230 :     Name of the desired column.
1231 :    
1232 :     =item location
1233 :    
1234 :     Location at which the desired column should be stored.
1235 :    
1236 :     =back
1237 :    
1238 :     =cut
1239 :    
1240 :     sub AddOptionalColumn {
1241 :     # Get the parameters.
1242 :     my ($self, $name => $loc) = @_;
1243 :     # Currently, there is no extra work required here, but that
1244 :     # may change.
1245 :     $self->_StoreColumnSpec($name, $loc);
1246 :     }
1247 :    
1248 :     =head3 PutExtraColumns
1249 :    
1250 : parrello 1.5 $rhelp->PutExtraColumns(name1 => value1, name2 => value2, ...);
1251 : parrello 1.1
1252 :     Store the values of one or more extra columns. If a search produces extra columns (that is,
1253 :     columns whose data is determined by the search instead of queries against the database), then
1254 :     for each row of output, the search must call this method to specify the values of the various
1255 :     extra columns. Multiple calls to this method are allowed, in which case each call either
1256 :     overrides or adds to the values specified by the prior call.
1257 :    
1258 :     =over 4
1259 :    
1260 :     =item extraColumnMap
1261 :    
1262 :     A hash keyed on extra column name that maps the column names to the column's values for the current
1263 :     row of table data.
1264 :    
1265 :     =back
1266 :    
1267 :     =cut
1268 :    
1269 :     sub PutExtraColumns {
1270 :     # Get the parameters.
1271 :     my ($self, %extraColumnMap) = @_;
1272 :     # Copy the hash values into the extra column hash.
1273 :     my $counter = 0;
1274 :     for my $name (keys %extraColumnMap) {
1275 :     $self->{extras}->{$name} = $extraColumnMap{$name};
1276 :     Trace("Extra column $name has value $extraColumnMap{$name}.") if T(4);
1277 :     }
1278 :     }
1279 :    
1280 :     =head2 Internal Utilities
1281 :    
1282 :     =head3 StoreColumnSpec
1283 :    
1284 : parrello 1.5 $rhelp->_StoreColumnSpec($column, $location);
1285 : parrello 1.1
1286 :     Store the specified column information at the specified location in the column name list.
1287 :     The information is a string for an ordinary column and a hash for an extra column. The
1288 :     actual location at which the column is stored will be adjusted so that there are no
1289 :     gaps in the list. If the location is undefined, it defaults to the end. Thus, C<0>
1290 :     will always store at the beginning and C<undef> will always store at the end.
1291 :    
1292 :     =over 4
1293 :    
1294 :     =item column
1295 :    
1296 :     A column name or extra-column hash to be stored in the column list.
1297 :    
1298 :     =item location
1299 :    
1300 :     The index at which the column name should be stored, or C<undef> to store it
1301 :     at the end.
1302 :    
1303 :     =back
1304 :    
1305 :     =cut
1306 :    
1307 :     sub _StoreColumnSpec {
1308 :     # Get the parameters.
1309 :     my ($self, $column, $location) = @_;
1310 :     # Compute the current column count.
1311 :     my $columnCount = scalar @{$self->{columns}};
1312 :     # Adjust the location.
1313 :     if (! defined($location) || $location > $columnCount) {
1314 :     $location = $columnCount;
1315 :     }
1316 :     # Insert the column into the list.
1317 :     splice @{$self->{columns}}, $location, 0, $column;
1318 :     }
1319 :    
1320 :    
1321 :     =head2 Virtual Methods
1322 :    
1323 :     The following methods can be overridden by the subclass. In some cases, they
1324 :     must be overridden.
1325 :    
1326 :     =head3 DefaultResultColumns
1327 :    
1328 : parrello 1.5 my @colNames = $rhelp->DefaultResultColumns();
1329 : parrello 1.1
1330 :     Return a list of the default columns to be used by searches with this
1331 :     type of result. Note that the actual default columns are computed by
1332 :     the search helper. This method is only needed if the search helper doesn't
1333 :     care.
1334 :    
1335 :     The columns returned should be in the form of column names, all of which
1336 :     must be defined by the result helper class.
1337 :    
1338 :     =cut
1339 :    
1340 :     sub DefaultResultColumns {
1341 :     # This method must be overridden.
1342 :     Confess("Pure virtual call to DefaultResultColumns.");
1343 :     }
1344 :    
1345 :     =head3 MoreDownloadFormats
1346 :    
1347 : parrello 1.5 $rhelp->MoreDownloadFormats(\%dlTypes);
1348 : parrello 1.1
1349 :     Add additional supported download formats to the type table. The table is a
1350 :     hash keyed on the download type code for which the values are the download
1351 :     descriptions. There is a special syntax that allows the placement of text
1352 :     fields inside the description. Use square brackets containing the name
1353 :     for the text field. The field will come in to the download request as
1354 :     a GET-type field.
1355 :    
1356 :     =over 4
1357 :    
1358 :     =item dlTypes
1359 :    
1360 :     Reference to a download-type hash. The purpose of this method is to add more
1361 :     download types relevant to the particular result type. Each type is described
1362 :     by a key (the download type itself) and a description. The description can
1363 :     contain a single text field that may be used to pass a parameter to the
1364 :     download. The text field is of the format C<[>I<fieldName>C<]>,
1365 :     where I<fieldName> is the name to give the text field's parameter in the
1366 :     generated download URL.
1367 :    
1368 :     =back
1369 :    
1370 :     =cut
1371 :    
1372 :     sub MoreDownloadFormats {
1373 :     Trace("Pure virtual call to MoreDownloadFormats.") if T(3);
1374 :     # Take no action.
1375 :     }
1376 :    
1377 :     =head3 MoreDownloadDataMethods
1378 :    
1379 : parrello 1.5 my @lines = $rhelp->MoreDownloadDataMethods($objectID, $dlType, \@cols, \@colHdrs);
1380 : parrello 1.1
1381 :     Create one or more lines of download data for a download of the specified type. Override
1382 :     this method if you need to process more download types than the default C<tbl> method.
1383 :    
1384 :     =over 4
1385 :    
1386 :     =item objectID
1387 :    
1388 :     ID of the object for this data row.
1389 :    
1390 :     =item dlType
1391 :    
1392 :     Download type (e.g. C<fasta>, etc.)
1393 :    
1394 :     =item cols
1395 :    
1396 :     Reference to a list of the data columns from the result cache, or alternatively
1397 :     the string C<header> (indicating that header lines are desired) or C<footer>
1398 :     (indicating that footer lines are desired).
1399 :    
1400 :     =item colHdrs
1401 :    
1402 :     The list of column headers from the result cache.
1403 :    
1404 :     =item RETURN
1405 :    
1406 :     Returns an array of data lines to output to the download file.
1407 :    
1408 :     =back
1409 :    
1410 :     =cut
1411 :    
1412 :     sub MoreDownloadDataMethods {
1413 :     # Get the parameters.
1414 :     my ($self, $objectID, $dlType, $cols, $colHdrs) = @_;
1415 :     # If we need to call this method, then the subclass should have overridden it.
1416 :     Confess("Invalid download type \"$dlType\" specified for result class $self->{type}.");
1417 :     }
1418 :    
1419 : parrello 1.5 1;

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3