source: trunk/gsdl/src/recpt/documentaction.cpp@ 533

Last change on this file since 533 was 533, checked in by sjboddie, 25 years ago

added GPL notice

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 32.6 KB
Line 
1/**********************************************************************
2 *
3 * documentaction.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * $Id: documentaction.cpp 533 1999-09-07 04:57:01Z sjboddie $
25 *
26 *********************************************************************/
27
28/*
29 $Log$
30 Revision 1.23 1999/09/07 04:56:54 sjboddie
31 added GPL notice
32
33 Revision 1.22 1999/08/20 01:00:22 sjboddie
34 split some of the larger functions up to simplify the creation of
35 collection specific receptionists
36
37 Revision 1.21 1999/08/11 23:28:03 sjboddie
38 -added support for html classifier
39 - removed _random_ macro - now use _blank for detach page
40
41 Revision 1.20 1999/08/10 23:16:39 sjboddie
42 a couple of small changes to get format options DocumentArrowsBottom
43 and DocumentArrowsTop working correctly
44
45 Revision 1.19 1999/08/10 22:40:01 sjboddie
46 added some more format options including the ability to format the
47 document text
48
49 Revision 1.18 1999/08/09 04:25:18 sjboddie
50 moved OID translation stuff from documentaction::define_external_macros
51 to receptionist
52
53 Revision 1.17 1999/08/09 02:13:53 sjboddie
54 fixed small bug in ShowSectionTitles
55
56 Revision 1.16 1999/08/03 03:30:47 sjboddie
57 a few small changes related to new format options
58
59 Revision 1.15 1999/07/30 02:18:49 sjboddie
60 -added collectinfo argument to some functions
61 -caught up with changes to browsetools (allowing nested classifications)
62 -added showtoppage format option
63
64 Revision 1.14 1999/07/21 05:01:09 sjboddie
65 fixed up wrapping of classificationlinks
66
67 Revision 1.13 1999/07/20 02:59:54 sjboddie
68 List and AZList classifications now use format strings
69
70 Revision 1.12 1999/07/16 00:19:01 sjboddie
71 some changes to the way quoted queries are handled
72
73 Revision 1.11 1999/07/07 05:47:41 sjboddie
74 changed around the way browsetools works
75
76 Revision 1.10 1999/06/29 01:46:44 sjboddie
77 now sets a _navigationbar_ macro even if there aren't any
78 classifications (it will just have the 'search' button
79
80 Revision 1.9 1999/06/27 22:05:58 sjboddie
81 now set a _thisOID_ macro for use in displaying images
82
83 Revision 1.8 1999/06/24 05:12:20 sjboddie
84 lots of small changes
85
86 Revision 1.7 1999/06/17 03:06:58 sjboddie
87 got detach button working properly - the close book icon is now disabled
88 when page is detached as the javascript close() function I was using is
89 too unreliable over different browsers
90 note that in my last comment I meant the "cl" arg (not the "c" arg).
91
92 Revision 1.6 1999/06/16 23:53:15 sjboddie
93 tidied a few things up. documentaction::define_external_macros now
94 resets the "c" arg if it's set to something stupid by the .xx suffixes
95
96 Revision 1.5 1999/06/16 03:10:49 sjboddie
97 define_internal_macros() now sets _pagetitle_ macro to document's title
98 (including parents of current document)
99
100 Revision 1.4 1999/06/15 01:55:29 sjboddie
101 - got text highlighting working
102 - got multiple collections working (now outputs error message if an
103 attempt is made to get a document when the "c" arg isn't set.
104
105 Revision 1.3 1999/06/08 04:29:37 sjboddie
106 added argsinfo to the call to check_cgiargs to make it easy to set
107 args to their default if they're found to be screwed up
108
109 Revision 1.2 1999/05/10 03:40:35 sjboddie
110 lots of changes - slowly getting document action sorted out
111
112 Revision 1.1 1999/04/30 01:59:40 sjboddie
113 lots of stuff - getting documentaction working (documentaction replaces
114 old browseaction)
115
116 Revision 1.2 1999/03/29 02:14:27 sjboddie
117
118 More changes to browseaction
119
120 Revision 1.1 1999/03/25 03:09:40 sjboddie
121
122 subjectbrowseaction became browseaction
123
124
125 */
126
127
128#include <string.h>
129#include "documentaction.h"
130#include "browsetools.h"
131#include "OIDtools.h"
132#include "querytools.h"
133#include "unitool.h"
134
135documentaction::documentaction () {
136 // this action uses cgi variables "a", "d", "cl",
137 // "x", "gc", "gt", "gp", and "hl"
138 cgiarginfo arg_ainfo;
139 arg_ainfo.shortname = "a";
140 arg_ainfo.longname = "action";
141 arg_ainfo.multiplechar = true;
142 arg_ainfo.defaultstatus = cgiarginfo::weak;
143 arg_ainfo.argdefault = "p";
144 arg_ainfo.savedarginfo = cgiarginfo::must;
145 argsinfo.addarginfo (NULL, arg_ainfo);
146
147 arg_ainfo.shortname = "d";
148 arg_ainfo.longname = "document OID";
149 arg_ainfo.multiplechar = true;
150 arg_ainfo.defaultstatus = cgiarginfo::none;
151 arg_ainfo.argdefault = "";
152 arg_ainfo.savedarginfo = cgiarginfo::can;
153 argsinfo.addarginfo (NULL, arg_ainfo);
154
155 arg_ainfo.shortname = "cl";
156 arg_ainfo.longname = "classification OID";
157 arg_ainfo.multiplechar = true;
158 arg_ainfo.defaultstatus = cgiarginfo::none;
159 arg_ainfo.argdefault = "";
160 arg_ainfo.savedarginfo = cgiarginfo::can;
161 argsinfo.addarginfo (NULL, arg_ainfo);
162
163 // in this action "gc" controls the expand/contract
164 // contents function
165 arg_ainfo.shortname = "gc";
166 arg_ainfo.longname = "expand contents";
167 arg_ainfo.multiplechar = false;
168 arg_ainfo.defaultstatus = cgiarginfo::weak;
169 arg_ainfo.argdefault = "0";
170 arg_ainfo.savedarginfo = cgiarginfo::can;
171 argsinfo.addarginfo (NULL, arg_ainfo);
172
173 // in this action "gt" controls the expand/contract
174 // text function 0 = not expanded, 1 = expand unless
175 // there are more than 10 sections containing text,
176 // 2 = expand all
177 arg_ainfo.shortname = "gt";
178 arg_ainfo.longname = "expand text";
179 arg_ainfo.multiplechar = false;
180 arg_ainfo.defaultstatus = cgiarginfo::weak;
181 arg_ainfo.argdefault = "0";
182 arg_ainfo.savedarginfo = cgiarginfo::can;
183 argsinfo.addarginfo (NULL, arg_ainfo);
184
185 // in this action "gp" is the "go to page" control
186 // used by the Book type of toc
187 arg_ainfo.shortname = "gp";
188 arg_ainfo.longname = "go to page";
189 arg_ainfo.multiplechar = true;
190 arg_ainfo.defaultstatus = cgiarginfo::none;
191 arg_ainfo.argdefault = "";
192 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
193 argsinfo.addarginfo (NULL, arg_ainfo);
194
195 // in this action "hl" is the "highlighting on/
196 // highlighting off control
197 arg_ainfo.shortname = "hl";
198 arg_ainfo.longname = "highlighting on/off";
199 arg_ainfo.multiplechar = false;
200 arg_ainfo.defaultstatus = cgiarginfo::weak;
201 arg_ainfo.argdefault = "1";
202 arg_ainfo.savedarginfo = cgiarginfo::must;
203 argsinfo.addarginfo (NULL, arg_ainfo);
204
205 // "x" is 0 normally or 1 if page
206 // has been "detached"
207 arg_ainfo.shortname = "x";
208 arg_ainfo.longname = "detached page";
209 arg_ainfo.multiplechar = false;
210 arg_ainfo.defaultstatus = cgiarginfo::weak;
211 arg_ainfo.argdefault = "0";
212 arg_ainfo.savedarginfo = cgiarginfo::must;
213 argsinfo.addarginfo (NULL, arg_ainfo);
214}
215
216documentaction::~documentaction () {
217}
218
219bool documentaction::init (ostream &logout) {
220 return action::init (logout);
221}
222
223bool documentaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
224 ostream &logout) {
225
226 // check gc argument
227 int arg_gc = args.getintarg("gc");
228 if (arg_gc != 0 && arg_gc != 1) {
229 logout << "Warning: \"gc\" argument out of range (" << arg_gc << ")\n";
230 cgiarginfo *gcinfo = argsinfo.getarginfo ("gc");
231 if (gcinfo != NULL) args["gc"] = gcinfo->argdefault;
232 }
233
234 // check gt argument (may be either 0, 1 or 2)
235 int arg_gt = args.getintarg("gt");
236 if (arg_gt != 0 && arg_gt != 1 && arg_gt != 2) {
237 logout << "Warning: \"gt\" argument out of range (" << arg_gt << ")\n";
238 cgiarginfo *gtinfo = argsinfo.getarginfo ("gt");
239 if (gtinfo != NULL) args["gt"] = gtinfo->argdefault;
240 }
241
242 // check hl argument
243 int arg_hl = args.getintarg("hl");
244 if (arg_hl != 0 && arg_hl != 1) {
245 logout << "Warning: \"hl\" argument out of range (" << arg_hl << ")\n";
246 cgiarginfo *hlinfo = argsinfo.getarginfo ("hl");
247 if (hlinfo != NULL) args["hl"] = hlinfo->argdefault;
248 }
249
250 // check x argument
251 int arg_x = args.getintarg("x");
252 if (arg_x != 0 && arg_x != 1) {
253 logout << "Warning: \"x\" argument out of range (" << arg_x << ")\n";
254 cgiarginfo *xinfo = argsinfo.getarginfo ("x");
255 if (xinfo != NULL) args["x"] = xinfo->argdefault;
256 }
257
258 return true;
259}
260
261void documentaction::get_cgihead_info (cgiargsclass &/*args*/, response_t &response,
262 text_t &response_data, ostream &/*logout*/) {
263 response = content;
264 response_data = "text/html";
265}
266
267
268// define all the macros which might be used by other actions
269// to produce pages.
270void documentaction::define_external_macros (const ColInfoResponse_t &/*collectinfo*/, displayclass &disp,
271 cgiargsclass &args, recptproto *collectproto,
272 ostream &logout) {
273
274 // define_external_macros sets the following macros:
275
276 // _navigationbar_ this is the navigation bar containing the search button
277 // and any classification buttons - it goes at the top of
278 // most pages. for now we're assuming that there'll always
279 // be a search button - we should probably check that there
280 // is a query action before making this assumption
281
282 // _httpbrowseXXX_ the http macros for each classification (i.e. if there
283 // are Title and Creator classifications _httpbrowseTitle_
284 // and _httpbrowseCreator_ will be set
285
286 // _javaimagesnavbar_ this is the javascript code to shove in to make the
287 // flashy images used by _navigationbar_ work
288
289
290 // can't do anything if collectproto is null (i.e. no collection was specified)
291 if (collectproto == NULL) return;
292
293 outconvertclass text_t2ascii;
294 comerror_t err;
295 InfoFiltersResponse_t filterinfo;
296 FilterResponse_t response;
297 text_tarray metadata;
298 text_t navigationbar, javaimagesnavbar, width, topparent;
299 int twidth, swidth, iwidth = 0;
300
301 text_t &arg_d = args["d"];
302 text_t &arg_cl = args["cl"];
303 text_t &collection = args["c"];
304
305 // don't want navigation bar if page is 'detached'
306 if (!args.getintarg("x")) {
307
308 get_top (arg_cl, topparent);
309
310 collectproto->get_filterinfo (collection, filterinfo, err, logout);
311 if (err == noError) {
312 // check that there's a browse filter
313 if (filterinfo.filterNames.find ("BrowseFilter") != filterinfo.filterNames.end()) {
314
315 metadata.push_back ("Title");
316 metadata.push_back ("classifytype");
317 bool getParents = false;
318 get_children ("", collection, metadata, getParents, collectproto, response, logout);
319
320 int numc = response.docInfo.size();
321 ResultDocInfo_tarray::const_iterator dochere = response.docInfo.begin();
322 ResultDocInfo_tarray::const_iterator docend = response.docInfo.end();
323
324 navigationbar = "<!-- Navigation Bar -->\n";
325
326 // calculate width of spacers and set macro
327 if (args.getintarg("v") == 0) {
328 disp.expandstring ("Global", "_pagewidth_", width);
329 twidth = width.getint();
330
331 disp.expandstring ("query", "_searchwidth_", width);
332 iwidth += width.getint();
333
334 while (dochere != docend) {
335 disp.expandstring ("document", "_" + (*dochere).metadata[0].values[0] + "width_", width);
336 iwidth += width.getint();
337 dochere ++;
338 }
339 if ((twidth - iwidth) < numc) swidth = 2;
340 else {
341 swidth = twidth - iwidth;
342 if (numc > 0) swidth = swidth / numc;
343 }
344 disp.setmacro ("widthtspace", "Global", swidth);
345 }
346
347 navigationbar += "<nobr>\n";
348 if (args["a"] == "q") {
349 navigationbar += "_icontabsearchgreen_";
350 } else {
351 navigationbar += "_imagesearch_";
352 javaimagesnavbar = "_javasearch_";
353 }
354 if (numc == 0) navigationbar += "_imagespacer_";
355
356 dochere = response.docInfo.begin();
357 while (dochere != docend) {
358 const text_t &title = (*dochere).metadata[0].values[0];
359 const text_t &classifytype = (*dochere).metadata[1].values[0];
360
361 // if we're inside a document all the classification buttons should be enabled
362 if (arg_d.empty() && ((*dochere).OID == topparent))
363 navigationbar += "_imagespacer__icontab" + title + "green_";
364 else {
365 navigationbar += "_imagespacer__image" + title + "_";
366
367 // set the _httpbrowseXXX_ macro for this classification
368 text_t link;
369 if (classifytype == "HTML")
370 link = "_httppagex_(html)&hp=" + (*dochere).OID + ".fc";
371 else
372 link = "_httpdocument_&cl=" + (*dochere).OID;
373
374 if (classifytype == "AZList" || classifytype == "DateList") link += ".fc";
375 disp.setmacro ("httpbrowse" + title, "Global", link);
376
377 }
378 javaimagesnavbar += "_java" + title + "_";
379 dochere ++;
380 }
381 navigationbar += "\n</nobr>\n";
382 navigationbar += "<!-- End of Navigation Bar -->\n";
383 disp.setmacro ("navigationbar", "Global", navigationbar);
384 if (args.getintarg("v") == 0)
385 disp.setmacro ("javaimagesnavbar", "Global", javaimagesnavbar);
386 }
387 } else {
388 logout << text_t2ascii
389 << "Error (documentaction::define_external_macros()) in call to get_filterinfo() "
390 << get_comerror_string (err);
391 }
392 }
393}
394
395
396void documentaction::load_formatinfo (const text_tmap &colformat, int gt) {
397
398 formatinfo.clear();
399 text_tmap::const_iterator format_here = colformat.begin();
400 text_tmap::const_iterator format_end = colformat.end();
401
402 while (format_here != format_end) {
403 if (((*format_here).first == "DocumentImages") &&
404 ((*format_here).second == "true"))
405 formatinfo.DocumentImages = true;
406 else if (((*format_here).first == "DocumentTopPages") &&
407 ((*format_here).second == "false"))
408 formatinfo.DocumentTopPages = false;
409 else if ((*format_here).first == "DocumentHeading")
410 formatinfo.DocumentHeading = (*format_here).second;
411 else if (((*format_here).first == "DocumentArrowsTop") &&
412 ((*format_here).second == "false"))
413 formatinfo.DocumentArrowsTop = false;
414 else if (((*format_here).first == "DocumentArrowsBottom") &&
415 ((*format_here).second == "false"))
416 formatinfo.DocumentArrowsBottom = false;
417 else if (((*format_here).first == "DocumentGoTo") &&
418 ((*format_here).second == "false"))
419 formatinfo.DocumentGoTo = false;
420 else if ((*format_here).first == "DocumentButtons")
421 splitchar ((*format_here).second.begin(), (*format_here).second.end(),
422 '|', formatinfo.DocumentButtons);
423 else if ((*format_here).first == "DocumentText")
424 formatinfo.DocumentText = (*format_here).second;
425
426 format_here ++;
427 }
428
429 // never want arrows when text is expanded
430 if (gt) {
431 formatinfo.DocumentArrowsBottom = false;
432 formatinfo.DocumentArrowsTop = false;
433 }
434}
435
436void documentaction::set_java_macros (cgiargsclass &args, displayclass &disp) {
437
438 text_t javaimagescontent = "_javaextras_";
439
440 int arg_gt = args.getintarg("gt");
441 int arg_gc = args.getintarg("gc");
442 int arg_hl = args.getintarg("hl");
443
444 text_tarray::const_iterator button_here = formatinfo.DocumentButtons.begin();
445 text_tarray::const_iterator button_end = formatinfo.DocumentButtons.end();
446
447 while (button_here != button_end) {
448 if (*button_here == "Detach")
449 javaimagescontent += "_javadetach_";
450 else if (*button_here == "Expand Text") {
451 if (arg_gt == 1)
452 javaimagescontent += "_javacontracttext__javacontinue_";
453 else if (arg_gt == 2)
454 javaimagescontent += "_javacontracttext_";
455 else
456 javaimagescontent += "_javaexpandtext_";
457 } else if (*button_here == "Expand Contents") {
458 if (arg_gc == 1)
459 javaimagescontent += "_javacontractcontents_";
460 else
461 javaimagescontent += "_javaexpandcontents_";
462 } else if (*button_here == "Highlight") {
463 if (arg_hl == 1)
464 javaimagescontent += "_javanohighlighting_";
465 else
466 javaimagescontent += "_javahighlighting_";
467 }
468 button_here ++;
469 }
470 disp.setmacro ("javaimagescontent", "document", javaimagescontent);
471}
472
473
474// sets the classificationlinks and navarrows macros
475void documentaction::get_classificationlinks (const text_t &arg_cl, const text_t &collection,
476 recptproto *collectproto, displayclass &disp,
477 ostream &logout) {
478
479 FilterResponse_t response;
480 text_t classificationlinks, navarrows, classtop;
481 text_tarray metadata;
482
483 metadata.push_back ("Title");
484 metadata.push_back ("doctype");
485 bool getParents = false;
486
487 get_top (arg_cl, classtop);
488 if (get_children (classtop, collection, metadata, getParents, collectproto, response, logout)) {
489
490 // don't want links unless there are 2 or more sections
491 if (response.docInfo.size() >= 2) {
492
493 classificationlinks += "<!-- Classification Links -->\n";
494 classificationlinks += "<table width=_pagewidth_ cellpadding=0 cellspacing=0 border=0>\n";
495 classificationlinks += "<tr><td valign=top><center>\n";
496
497 ResultDocInfo_tarray::const_iterator sechere = response.docInfo.begin();
498 ResultDocInfo_tarray::const_iterator secend = response.docInfo.end();
499
500 int lenlinks = 0;
501 while (sechere != secend) {
502 if ((*sechere).metadata[1].values[0] == "classify") {
503 const text_t &sectionheading = (*sechere).metadata[0].values[0];
504
505 if (((*sechere).OID == arg_cl) || is_child_of((*sechere).OID, arg_cl)) {
506
507 // set the _httpprevarrow_, _httpnextarrow_ macros while we're here
508 if (formatinfo.DocumentArrowsBottom) {
509 if (sechere != response.docInfo.begin())
510 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&cl=" + (*(sechere-1)).OID);
511 if ((sechere + 1) != secend)
512 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&cl=" + (*(sechere+1)).OID);
513 }
514
515 lenlinks += sectionheading.size();
516 classificationlinks += "<b>" + sectionheading + "</b>";
517 if (lenlinks > 50) {
518 classificationlinks += "<br>\n";
519 lenlinks = 0;
520 } else {
521 if (sechere+1 != secend) classificationlinks += "&nbsp;&nbsp;&nbsp;\n";
522 lenlinks += 3;
523 }
524 } else {
525 lenlinks += sectionheading.size();
526 classificationlinks += "<a href=\"_httpdocument_&cl=" + (*sechere).OID + "\">";
527 classificationlinks += sectionheading + "</a>";
528 if (lenlinks > 50) {
529 classificationlinks += "<br>\n";
530 lenlinks = 0;
531 } else {
532 if (sechere+1 != secend) classificationlinks += "&nbsp;&nbsp;&nbsp;\n";
533 lenlinks += 3;
534 }
535 }
536 }
537 sechere ++;
538 }
539
540 classificationlinks += "\n</center></td></tr></table>\n";
541 classificationlinks += "<!-- End of Classification Links -->\n";
542
543 disp.setmacro ("classificationlinks", "document", classificationlinks);
544 }
545 }
546}
547
548
549// define all the macros which are related to pages generated
550// by this action. we also load up the formatinfo structure
551// here (it's used in do_action as well as here)
552void documentaction::define_internal_macros (const ColInfoResponse_t &collectinfo, displayclass &disp,
553 cgiargsclass &args, recptproto *collectproto,
554 ostream &logout) {
555
556 // define_internal_macros sets the following macros:
557
558 // _pagetitle_ the title to be displayed at the top of the browser window
559
560 // _imagethispage_ the title image to be displayed at top right of page
561
562 // _classificationlinks_ the links between classifications to be displayed
563 // at top of list or datelist classifications
564
565 // _httpprevarrow_ these are set if next or previous arrows
566 // _httpnextarrow_ are to be used - (i.e. if it's an AZList or a DateList
567 // classifytype at a top level or if it's a Book or a
568 // Hierarchy classifytype at document level
569
570 // _navarrows_ this may be overridden to "" when format option
571 // DocumentArrowsBottom is false
572
573 // _header_ the header macro is overridden if we're not at a top level
574 // classification to remove the title block
575
576 // _javaimagescontent_ this is the javascript code to shove in to make the
577 // flashy buttons work
578
579 // _thisOID_ the OID (directory) of the current document - this corresponds
580 // to the archivedir metadata element
581
582 // can't do anything if collectproto is null (i.e. no collection was specified)
583 if (collectproto == NULL) return;
584
585 text_tarray metadata;
586 FilterResponse_t response;
587 text_t &arg_d = args["d"];
588 text_t &arg_cl = args["cl"];
589 text_t &collection = args["c"];
590 int gt = args.getintarg("gt");
591 load_formatinfo (collectinfo.format, gt);
592
593 if (!formatinfo.DocumentArrowsBottom)
594 disp.setmacro("navarrows", "document", "");
595
596 metadata.push_back ("Title");
597 metadata.push_back ("classifytype");
598 metadata.push_back ("archivedir");
599
600 if (!arg_d.empty()) {
601 // we're at document level
602
603 // get metadata for this document and it's parents
604 if (get_info (arg_d, collection, metadata, true, collectproto, response, logout)) {
605 disp.setmacro ("header", "document", "_textheader_");
606
607 text_t pagetitle;
608 if (gt)
609 pagetitle = *(response.docInfo[0].metadata[0].values.begin());
610 else {
611 text_tarray::const_iterator this_title = response.docInfo[0].metadata[0].values.begin();
612 text_tarray::const_iterator end_title = response.docInfo[0].metadata[0].values.end();
613 while (this_title != end_title) {
614 if ((this_title + 1) == end_title) pagetitle += *this_title;
615 else pagetitle += *this_title + ": ";
616 this_title ++;
617 }
618 }
619 disp.setmacro ("pagetitle", "document", pagetitle);
620 disp.setmacro ("thisOID", "Global", response.docInfo[0].metadata[2].values[0]);
621
622 text_t &classifytype = response.docInfo[0].metadata[1].values[0];
623 if (classifytype.empty()) classifytype = "Book"; // defaults to Book
624
625 // set arrow macros if required
626 if (((classifytype == "Book") && (formatinfo.DocumentArrowsTop || formatinfo.DocumentArrowsBottom)) ||
627 ((classifytype == "Hierarchy") && formatinfo.DocumentArrowsBottom))
628 set_arrow_macros (arg_d, classifytype, formatinfo.DocumentTopPages,
629 disp, collectproto, collection, logout);
630
631 if (args["u"] != "1")
632 set_java_macros (args, disp);
633
634 }
635 } else {
636 if (!arg_cl.empty()) {
637
638 // get metadata for top level classification
639 text_t classtop;
640 get_top (arg_cl, classtop);
641 if (get_info (classtop, collection, metadata, false, collectproto, response, logout)) {
642
643 text_t &title = response.docInfo[0].metadata[0].values[0];
644 text_t &classifytype = response.docInfo[0].metadata[1].values[0];
645
646 disp.setmacro ("pagetitle", "document", "_text" + title + "page_");
647 disp.setmacro ("imagethispage", "document", "_icon" + title + "page_");
648
649 // now get the metadata for each child of top level
650 // so we can generate the _classificationlinks_ and arrow macros
651 // (if they're required by the current classification type)
652
653 if ((classifytype == "AZList") || (classifytype == "DateList"))
654 get_classificationlinks (arg_cl, collection, collectproto, disp, logout);
655
656 }
657 }
658 }
659}
660
661
662bool documentaction::do_action (cgiargsclass &args, const ColInfoResponse_t &collectinfo,
663 recptproto *collectproto, displayclass &disp,
664 outconvertclass &outconvert, ostream &textout,
665 ostream &logout) {
666
667 if (collectproto == NULL) {
668 logout << "documentaction::do_action called with NULL collectproto\n";
669 textout << outconvert << disp << "_document:header_\n"
670 << "Error: Attempt to get document without setting collection\n"
671 << "_document:footer_\n";
672 } else {
673
674 text_tarray metadata;
675 FilterResponse_t response;
676 text_t toptitle, toptype, thistype, formatstring;
677
678 text_t &collection = args["c"];
679 text_t &arg_d = args["d"];
680 text_t &arg_cl = args["cl"];
681
682 text_t OID = arg_d;
683 if (arg_d.empty()) OID = arg_cl;
684
685 textout << outconvert << disp << "_document:header_\n"
686 << "_document:content_\n";
687
688 if (arg_d.empty() && arg_cl.empty()) {
689 textout << outconvert << disp << "Document contains no data_document:footer_\n";
690 return true;
691 }
692
693 // get the classifytitle and classifytype for both the top level
694 // and the current level (using getParent=true)
695 metadata.push_back ("Title");
696 metadata.push_back ("classifytype");
697 if (get_info (OID, collection, metadata, true, collectproto, response, logout)) {
698 toptitle = response.docInfo[0].metadata[0].values[0];
699 toptype = response.docInfo[0].metadata[1].values[0];
700 thistype = response.docInfo[0].metadata[1].values.back();
701 }
702
703 text_t formatkey = toptype + toptitle;
704 if (!arg_d.empty()) formatkey = toptype + "Document";
705
706 text_tmap::const_iterator it = collectinfo.format.find(formatkey);
707 if (it != collectinfo.format.end()) formatstring = (*it).second;
708
709 // output the table of contents
710 if (!arg_d.empty()) {
711
712 if (toptype == "Hierarchy")
713 output_standard_toc (thistype, formatinfo, formatstring, args,
714 collectproto, disp, outconvert, textout, logout);
715
716 else
717 output_document_toc (args, formatinfo, collectproto, disp,
718 outconvert, textout, logout);
719
720 } else {
721 output_standard_toc (thistype, formatinfo, formatstring, args,
722 collectproto, disp, outconvert, textout, logout);
723 }
724
725 // output the document text
726 textout << "<p>\n";
727 output_document (OID, args, collectproto, disp, outconvert, textout, logout);
728
729 textout << outconvert << disp << "_document:footer_\n";
730 }
731 return true;
732}
733
734void documentaction::output_text (const ResultDocInfo_t &docinfo, format_t *formatlistptr,
735 const TermInfo_tarray &terminfo, const text_t &OID,
736 bool highlight, const text_t &hastxt, int wanttext,
737 text_t &collection, recptproto *collectproto, displayclass &disp,
738 outconvertclass &outconvert, ostream &textout,
739 ostream &logout) {
740
741 DocumentRequest_t docrequest;
742 DocumentResponse_t docresponse;
743 comerror_t err;
744
745 if (hastxt == "1") {
746
747 if (wanttext) {
748 // get the text
749 docrequest.OID = OID;
750 collectproto->get_document (collection, docrequest, docresponse, err, logout);
751
752 // cut down on overhead by not using formattools if we only want the text
753 // (wanttext will equal 2 if we want text and other stuff too)
754 if (wanttext == 1)
755 if (highlight)
756 highlighttext(docresponse.doc, terminfo, disp, outconvert, textout, logout);
757 else
758 textout << outconvert << disp << docresponse.doc;
759 }
760
761 if (wanttext != 1) {
762 text_t doctext = get_formatted_string (docinfo, formatlistptr, docresponse.doc);
763
764 if (highlight)
765 highlighttext(doctext, terminfo, disp, outconvert, textout, logout);
766 else
767 textout << outconvert << disp << doctext;
768 }
769 }
770}
771
772
773void documentaction::output_document (const text_t &OID, cgiargsclass &args,
774 recptproto *collectproto, displayclass &disp,
775 outconvertclass &outconvert, ostream &textout,
776 ostream &logout) {
777 FilterResponse_t inforesponse;
778 FilterResponse_t queryresponse;
779 text_tarray metadata;
780 bool getParents = false;
781 bool highlight = false;
782 int wanttext = 0;
783 int arg_gt = args.getintarg("gt");
784 text_t &collection = args["c"];
785
786 // if we have a query string and highlighting is turned on we need
787 // to redo the query to get the terms for highlighting
788 if (!args["q"].empty() && args.getintarg("hl")) {
789 FilterRequest_t request;
790 request.filterResultOptions = FRmatchTerms;
791 if (do_query (request, args, collectproto, queryresponse, logout))
792 highlight = true;
793 }
794
795 format_t *formatlistptr = new format_t();
796 parse_formatstring (formatinfo.DocumentText, formatlistptr, metadata, getParents);
797
798 metadata.push_back("hastxt");
799 metadata.push_back("haschildren");
800
801 if (formatinfo.DocumentText == "[Text]")
802 wanttext = 1;
803 else {
804 char *docformat = formatinfo.DocumentText.getcstr();
805 if (strstr (docformat, "[Text]") != NULL)
806 wanttext = 2;
807 delete docformat;
808 }
809
810 int metasize = metadata.size();
811
812 if (get_info (OID, collection, metadata, getParents, collectproto, inforesponse, logout)) {
813 text_t hastxt = inforesponse.docInfo[0].metadata[metasize-2].values.back();
814 text_t &haschildren = inforesponse.docInfo[0].metadata[metasize-1].values.back();
815
816 if (arg_gt == 0) {
817 output_text (inforesponse.docInfo[0], formatlistptr, queryresponse.termInfo,
818 OID, highlight, hastxt, wanttext, collection, collectproto,
819 disp, outconvert, textout, logout);
820
821
822 } else {
823
824 ResultDocInfo_t thisdocinfo = inforesponse.docInfo[0];
825
826 // text is to be expanded
827 text_t exOID = OID;
828 if (haschildren != "1") exOID = get_parent (OID);
829 if (exOID.empty()) exOID = OID;
830
831 // if we're not in a document (i.e. we're in a top level classification)
832 // we need to pass the "classify" string to get_contents so that it
833 // doesn't recurse all the way through each document in the classification
834 text_t classifytype;
835 if (args["d"].empty()) classifytype = "classify";
836
837 int i = 0; // not used
838 get_contents (exOID, classifytype, metadata, i, collection,
839 collectproto, inforesponse, logout);
840
841 ResultDocInfo_tarray::const_iterator sechere = inforesponse.docInfo.begin();
842 ResultDocInfo_tarray::const_iterator secend = inforesponse.docInfo.end();
843
844 if (arg_gt == 1) {
845 // check if there are more than 10 sections containing text to be expanded -
846 // if there are output warning message - this isn't a great way to do this
847 // since the sections may be very large or very small - one day I'll fix it
848 // -- Stefan.
849 int seccount = 0;
850 while (sechere != secend) {
851 const text_t &shastxt = (*sechere).metadata[metasize-2].values.back();
852 if (shastxt == "1") seccount ++;
853 if (seccount > 10) break;
854 sechere ++;
855 }
856 if (seccount > 10) {
857 // more than 10 sections so output warning message and text
858 // for current section only
859 textout << outconvert << disp << "_document:textltwarning_";
860
861 output_text (thisdocinfo, formatlistptr, queryresponse.termInfo,
862 OID, highlight, hastxt, wanttext, collection,
863 collectproto, disp, outconvert, textout, logout);
864
865 }
866 else arg_gt = 2;
867 }
868
869 if (arg_gt == 2) {
870 // get the text for each section
871 sechere = inforesponse.docInfo.begin();
872 int count = 0;
873 while (sechere != secend) {
874 textout << outconvert << disp << "\n<p><a name=" << count << "></a>\n";
875
876 const text_t &shastxt = (*sechere).metadata[metasize-2].values.back();
877
878 output_text (*sechere, formatlistptr, queryresponse.termInfo,
879 (*sechere).OID, highlight, shastxt, wanttext, collection,
880 collectproto, disp, outconvert, textout, logout);
881 count ++;
882 sechere ++;
883 }
884 }
885 }
886 }
887 delete formatlistptr;
888}
889
890// highlighttext highlights query terms in text string and outputs the resulting text string
891void documentaction::highlighttext(text_t &text, const TermInfo_tarray &terms,
892 displayclass &disp, outconvertclass &outconvert,
893 ostream &textout, ostream &/*logout*/) {
894
895 text_tmap allterms;
896 text_tmap::const_iterator it;
897
898 // first load all the term variations into a map
899 TermInfo_tarray::const_iterator this_term = terms.begin();
900 TermInfo_tarray::const_iterator last_term = terms.end();
901 while (this_term != last_term) {
902 text_tarray::const_iterator this_var = (*this_term).matchTerms.begin();
903 text_tarray::const_iterator last_var = (*this_term).matchTerms.end();
904 while (this_var != last_var) {
905 allterms[*this_var] = 1;
906 this_var ++;
907 }
908 this_term ++;
909 }
910
911 // get the text to start and end a hightlight
912 text_t starthighlight = "<b><u>";
913 text_t endhighlight = "</u></b>";
914 if (disp.isdefaultmacro("Global", "starthighlight"))
915 disp.expandstring("Global", "_starthighlight_", starthighlight);
916 if (disp.isdefaultmacro("Global", "endhighlight"))
917 disp.expandstring("Global", "_endhighlight_", endhighlight);
918
919
920 text_t::iterator here = text.begin();
921 text_t::iterator end = text.end();
922 text_t word, buffer;
923 while (here != end) {
924 if (is_unicode_letdig(*here)) {
925 // not word boundary
926 word.push_back(*here);
927 here++;
928
929 } else {
930 // found word boundary
931 // add last word if there was one
932 if (!word.empty()) {
933 it = allterms.find(word);
934 if (it != allterms.end()) {
935 word = starthighlight + word + endhighlight;
936 }
937 buffer += word;
938 word.clear();
939 }
940
941 if (*here == '<') {
942 // skip over rest of html tag
943 while ((here != end) && (*here != '>')) {
944 buffer.push_back(*here);
945 here++;
946 }
947 }
948
949 buffer.push_back(*here);
950 here++;
951
952 if (buffer.size() > 1024) {
953 textout << outconvert << disp << buffer;
954 buffer.clear();
955 }
956 }
957 }
958 textout << outconvert << disp << buffer;
959}
Note: See TracBrowser for help on using the repository browser.