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

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

changed around the way browsetools works

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 27.8 KB
Line 
1/**********************************************************************
2 *
3 * documentaction.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * PUT COPYRIGHT NOTICE HERE
7 *
8 * $Id: documentaction.cpp 346 1999-07-07 05:47:41Z sjboddie $
9 *
10 *********************************************************************/
11
12/*
13 $Log$
14 Revision 1.11 1999/07/07 05:47:41 sjboddie
15 changed around the way browsetools works
16
17 Revision 1.10 1999/06/29 01:46:44 sjboddie
18 now sets a _navigationbar_ macro even if there aren't any
19 classifications (it will just have the 'search' button
20
21 Revision 1.9 1999/06/27 22:05:58 sjboddie
22 now set a _thisOID_ macro for use in displaying images
23
24 Revision 1.8 1999/06/24 05:12:20 sjboddie
25 lots of small changes
26
27 Revision 1.7 1999/06/17 03:06:58 sjboddie
28 got detach button working properly - the close book icon is now disabled
29 when page is detached as the javascript close() function I was using is
30 too unreliable over different browsers
31 note that in my last comment I meant the "cl" arg (not the "c" arg).
32
33 Revision 1.6 1999/06/16 23:53:15 sjboddie
34 tidied a few things up. documentaction::define_external_macros now
35 resets the "c" arg if it's set to something stupid by the .xx suffixes
36
37 Revision 1.5 1999/06/16 03:10:49 sjboddie
38 define_internal_macros() now sets _pagetitle_ macro to document's title
39 (including parents of current document)
40
41 Revision 1.4 1999/06/15 01:55:29 sjboddie
42 - got text highlighting working
43 - got multiple collections working (now outputs error message if an
44 attempt is made to get a document when the "c" arg isn't set.
45
46 Revision 1.3 1999/06/08 04:29:37 sjboddie
47 added argsinfo to the call to check_cgiargs to make it easy to set
48 args to their default if they're found to be screwed up
49
50 Revision 1.2 1999/05/10 03:40:35 sjboddie
51 lots of changes - slowly getting document action sorted out
52
53 Revision 1.1 1999/04/30 01:59:40 sjboddie
54 lots of stuff - getting documentaction working (documentaction replaces
55 old browseaction)
56
57 Revision 1.2 1999/03/29 02:14:27 sjboddie
58
59 More changes to browseaction
60
61 Revision 1.1 1999/03/25 03:09:40 sjboddie
62
63 subjectbrowseaction became browseaction
64
65
66 */
67
68
69#include "documentaction.h"
70#include "browsetools.h"
71#include "OIDtools.h"
72#include "querytools.h"
73#include "unitool.h"
74
75documentaction::documentaction () {
76 // this action uses cgi variables "a", "d", "cl",
77 // "x", "gc", "gt", "gp", and "hl"
78 cgiarginfo arg_ainfo;
79 arg_ainfo.shortname = "a";
80 arg_ainfo.longname = "action";
81 arg_ainfo.multiplechar = true;
82 arg_ainfo.defaultstatus = cgiarginfo::weak;
83 arg_ainfo.argdefault = "p";
84 arg_ainfo.savedarginfo = cgiarginfo::must;
85 argsinfo.addarginfo (NULL, arg_ainfo);
86
87 arg_ainfo.shortname = "d";
88 arg_ainfo.longname = "document OID";
89 arg_ainfo.multiplechar = true;
90 arg_ainfo.defaultstatus = cgiarginfo::none;
91 arg_ainfo.argdefault = "";
92 arg_ainfo.savedarginfo = cgiarginfo::can;
93 argsinfo.addarginfo (NULL, arg_ainfo);
94
95 arg_ainfo.shortname = "cl";
96 arg_ainfo.longname = "classification OID";
97 arg_ainfo.multiplechar = true;
98 arg_ainfo.defaultstatus = cgiarginfo::none;
99 arg_ainfo.argdefault = "";
100 arg_ainfo.savedarginfo = cgiarginfo::can;
101 argsinfo.addarginfo (NULL, arg_ainfo);
102
103 // in this action "gc" controls the expand/contract
104 // contents function
105 arg_ainfo.shortname = "gc";
106 arg_ainfo.longname = "expand contents";
107 arg_ainfo.multiplechar = false;
108 arg_ainfo.defaultstatus = cgiarginfo::weak;
109 arg_ainfo.argdefault = "0";
110 arg_ainfo.savedarginfo = cgiarginfo::can;
111 argsinfo.addarginfo (NULL, arg_ainfo);
112
113 // in this action "gt" controls the expand/contract
114 // text function 0 = not expanded, 1 = expand unless
115 // there are more than 10 sections containing text,
116 // 2 = expand all
117 arg_ainfo.shortname = "gt";
118 arg_ainfo.longname = "expand text";
119 arg_ainfo.multiplechar = false;
120 arg_ainfo.defaultstatus = cgiarginfo::weak;
121 arg_ainfo.argdefault = "0";
122 arg_ainfo.savedarginfo = cgiarginfo::can;
123 argsinfo.addarginfo (NULL, arg_ainfo);
124
125 // in this action "gp" is the "go to page" control
126 // used by the Book type of toc
127 arg_ainfo.shortname = "gp";
128 arg_ainfo.longname = "go to page";
129 arg_ainfo.multiplechar = true;
130 arg_ainfo.defaultstatus = cgiarginfo::none;
131 arg_ainfo.argdefault = "";
132 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
133 argsinfo.addarginfo (NULL, arg_ainfo);
134
135 // in this action "hl" is the "highlighting on/
136 // highlighting off control
137 arg_ainfo.shortname = "hl";
138 arg_ainfo.longname = "highlighting on/off";
139 arg_ainfo.multiplechar = false;
140 arg_ainfo.defaultstatus = cgiarginfo::weak;
141 arg_ainfo.argdefault = "1";
142 arg_ainfo.savedarginfo = cgiarginfo::must;
143 argsinfo.addarginfo (NULL, arg_ainfo);
144
145 // "x" is 0 normally or 1 if page
146 // has been "detached"
147 arg_ainfo.shortname = "x";
148 arg_ainfo.longname = "detached page";
149 arg_ainfo.multiplechar = false;
150 arg_ainfo.defaultstatus = cgiarginfo::weak;
151 arg_ainfo.argdefault = "0";
152 arg_ainfo.savedarginfo = cgiarginfo::must;
153 argsinfo.addarginfo (NULL, arg_ainfo);
154}
155
156documentaction::~documentaction () {
157}
158
159bool documentaction::init (ostream &logout) {
160 return action::init (logout);
161}
162
163bool documentaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
164 ostream &logout) {
165
166 // note that "gp" argument gets checked in define_external_macros()
167
168 // check gc argument
169 int arg_gc = args.getintarg("gc");
170 if (arg_gc != 0 && arg_gc != 1) {
171 logout << "Warning: \"gc\" argument out of range (" << arg_gc << ")\n";
172 cgiarginfo *gcinfo = argsinfo.getarginfo ("gc");
173 if (gcinfo != NULL) args["gc"] = gcinfo->argdefault;
174 }
175
176 // check gt argument (may be either 0, 1 or 2)
177 int arg_gt = args.getintarg("gt");
178 if (arg_gt != 0 && arg_gt != 1 && arg_gt != 2) {
179 logout << "Warning: \"gt\" argument out of range (" << arg_gt << ")\n";
180 cgiarginfo *gtinfo = argsinfo.getarginfo ("gt");
181 if (gtinfo != NULL) args["gt"] = gtinfo->argdefault;
182 }
183
184 // check hl argument
185 int arg_hl = args.getintarg("hl");
186 if (arg_hl != 0 && arg_hl != 1) {
187 logout << "Warning: \"hl\" argument out of range (" << arg_hl << ")\n";
188 cgiarginfo *hlinfo = argsinfo.getarginfo ("hl");
189 if (hlinfo != NULL) args["hl"] = hlinfo->argdefault;
190 }
191
192 // check x argument
193 int arg_x = args.getintarg("x");
194 if (arg_x != 0 && arg_x != 1) {
195 logout << "Warning: \"x\" argument out of range (" << arg_x << ")\n";
196 cgiarginfo *xinfo = argsinfo.getarginfo ("x");
197 if (xinfo != NULL) args["x"] = xinfo->argdefault;
198 }
199
200 return true;
201}
202
203void documentaction::get_cgihead_info (cgiargsclass &/*args*/, response_t &response,
204 text_t &response_data, ostream &/*logout*/) {
205 response = content;
206 response_data = "text/html";
207}
208
209
210// define all the macros which might be used by other actions
211// to produce pages.
212void documentaction::define_external_macros (displayclass &disp, cgiargsclass &args,
213 recptproto *collectproto, ostream &logout) {
214
215 // define_external_macros sets the following macros:
216
217 // _navigationbar_ this is the navigation bar containing the search button
218 // and any classification buttons - it goes at the top of
219 // most pages. for now we're assuming that there'll always
220 // be a search button - we should probably check that there
221 // is a query action before making this assumption
222
223 // _httpbrowseXXX_ the http macros for each classification (i.e. if there
224 // are Title and Creator classifications _httpbrowseTitle_
225 // and _httpbrowseCreator_ will be set
226
227 // _javaimagesnavbar_ this is the javascript code to shove in to make the
228 // flashy images used by _navigationbar_ work
229
230 // _cgiargd_ these are overridden if they use the tricky ".xx" syntax
231 // _cgiargcl_
232
233 // can't do anything if collectproto is null (i.e. no collection was specified)
234 if (collectproto == NULL) return;
235
236 outconvertclass text_t2ascii;
237 comerror_t err;
238 InfoFiltersResponse_t filterinfo;
239 FilterResponse_t response;
240 FilterRequest_t request;
241 text_tarray metadata;
242 text_t navigationbar, javaimagesnavbar, width, topparent;
243 int twidth, swidth, iwidth = 0;
244
245 text_t &arg_d = args["d"];
246 text_t &arg_cl = args["cl"];
247 text_t &collection = args["c"];
248
249 // if the "gp" (go to page) argument is set we need to set
250 // the "d" argument to the corresponding page
251 if ((!arg_d.empty()) && (!args["gp"].empty()) &&
252 (is_number (args["gp"]))) {
253 text_t top;
254 get_top (arg_d, top);
255 metadata.push_back ("Title");
256 get_children (top, collection, metadata, collectproto, response, logout);
257 ResultDocInfo_tarray::const_iterator dochere = response.docInfo.begin();
258 ResultDocInfo_tarray::const_iterator docend = response.docInfo.end();
259 while (dochere != docend) {
260 if ((*dochere).metadata[0].values[0] == args["gp"]) {
261 arg_d = (*dochere).OID;
262 disp.setmacro ("cgiargd", "Global", arg_d);
263 break;
264 }
265 dochere ++;
266 }
267 metadata.erase (metadata.begin(), metadata.end());
268 }
269
270 // do a call to translate OIDs if required
271 request.filterName = "NullFilter";
272 request.filterResultOptions = FROID;
273 if (needs_translating (arg_d)) {
274 request.docSet.insert (arg_d);
275 collectproto->filter (collection, request, response, err, logout);
276 arg_d = response.docInfo[0].OID;
277 request.docSet.erase (request.docSet.begin(), request.docSet.end());
278 disp.setmacro ("cgiargd", "Global", arg_d);
279 }
280 // we'll also check here that the "cl" argument has a "classify" doctype
281 // (in case ".fc" or ".lc" have screwed up)
282 if (needs_translating (arg_cl)) {
283 request.fields.push_back("doctype");
284 request.docSet.insert (arg_cl);
285 request.filterResultOptions = FRmetadata;
286 collectproto->filter (collection, request, response, err, logout);
287 // set to original value (without .xx stuff) if doctype isn't "classify"
288 if (response.docInfo[0].metadata[0].values[0] != "classify")
289 strip_suffix (arg_cl);
290 else
291 arg_cl = response.docInfo[0].OID;
292 disp.setmacro ("cgiargcl", "Global", arg_cl);
293 }
294
295 // don't want navigation bar if page is 'detached'
296 if (!args.getintarg("x")) {
297
298 get_top (arg_cl, topparent);
299
300 collectproto->get_filterinfo (collection, filterinfo, err, logout);
301 if (err == noError) {
302 // check that there's a browse filter
303 if (filterinfo.filterNames.find ("BrowseFilter") != filterinfo.filterNames.end()) {
304
305 metadata.push_back ("Title");
306 metadata.push_back ("classifytype");
307 get_children ("", collection, metadata, collectproto, response, logout);
308
309 int numc = response.docInfo.size();
310 ResultDocInfo_tarray::const_iterator dochere = response.docInfo.begin();
311 ResultDocInfo_tarray::const_iterator docend = response.docInfo.end();
312
313 navigationbar = "<!-- Navigation Bar -->\n";
314
315 // calculate width of spacers and set macro
316 if (args.getintarg("v") == 0) {
317 disp.expandstring ("Global", "_pagewidth_", width);
318 twidth = width.getint();
319
320 disp.expandstring ("query", "_searchwidth_", width);
321 iwidth += width.getint();
322
323 while (dochere != docend) {
324 disp.expandstring ("document", "_" + (*dochere).metadata[0].values[0] + "width_", width);
325 iwidth += width.getint();
326 dochere ++;
327 }
328 if ((twidth - iwidth) < numc) swidth = 2;
329 else {
330 swidth = twidth - iwidth;
331 if (numc > 0) swidth = swidth / numc;
332 }
333 disp.setmacro ("widthtspace", "Global", swidth);
334 }
335
336 navigationbar += "<nobr>\n";
337 if (args["a"] == "q") {
338 navigationbar += "_icontabsearchgreen_";
339 } else {
340 navigationbar += "_imagesearch_";
341 javaimagesnavbar = "_javasearch_";
342 }
343 if (numc == 0) navigationbar += "_imagespacer_";
344
345 dochere = response.docInfo.begin();
346 while (dochere != docend) {
347 const text_t &title = (*dochere).metadata[0].values[0];
348 const text_t &classifytype = (*dochere).metadata[1].values[0];
349
350 // if we're inside a document all the classification buttons should be enabled
351 if (arg_d.empty() && ((*dochere).OID == topparent))
352 navigationbar += "_imagespacer__icontab" + title + "green_";
353 else {
354 navigationbar += "_imagespacer__image" + title + "_";
355
356 // set the _httpbrowseXXX_ macro for this classification
357 text_t link = (*dochere).OID;
358 if (classifytype == "AZList" || classifytype == "Datelist") link += ".fc";
359 disp.setmacro ("httpbrowse" + title, "Global",
360 "_httpdocument_&cl=" + link);
361 }
362 javaimagesnavbar += "_java" + title + "_";
363 dochere ++;
364 }
365 navigationbar += "\n</nobr>\n";
366 navigationbar += "<!-- End of Navigation Bar -->\n";
367 disp.setmacro ("navigationbar", "Global", navigationbar);
368 if (args.getintarg("v") == 0)
369 disp.setmacro ("javaimagesnavbar", "Global", javaimagesnavbar);
370 }
371 } else {
372 logout << text_t2ascii
373 << "Error (documentaction::define_external_macros()) in call to get_filterinfo() "
374 << get_comerror_string (err);
375 }
376 }
377}
378
379
380// define all the macros which are related to pages generated
381// by this action
382void documentaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
383 recptproto *collectproto, ostream &logout) {
384
385 // define_internal_macros sets the following macros:
386
387 // _random_ a random number - used for setting target tags to display
388 // a random page when you hit the 'detach' button
389
390 // _pagetitle_ the title to be displayed at the top of the browser window
391
392 // _imagethispage_ the title image to be displayed at top right of page
393
394 // _classificationlinks_ the links between classifications to be displayed
395 // at top of list or datelist classifications
396
397 // _httpprevarrow_ these are set if next or previous arrows
398 // _httpnextarrow_ are to be used - (i.e. if it's an AZList or a Datelist
399 // classifytype at a top level or if it's a Book or a
400 // Hierarchy classifytype at document level
401
402 // _header_ the header macro is overridden if we're not at a top level
403 // classification to remove the title block
404
405 // _javaimagescontent_ this is the javascript code to shove in to make the
406 // flashy buttons work
407
408 // _thisOID_ the OID (directory) of the current document - this corresponds
409 // to the archivedir metadata element
410
411
412 // can't do anything if collectproto is null (i.e. no collection was specified)
413 if (collectproto == NULL) return;
414
415 disp.setmacro("random", "document", rand());
416
417 text_tarray metadata;
418 FilterResponse_t response;
419 text_t &arg_d = args["d"];
420 text_t &arg_cl = args["cl"];
421 text_t &collection = args["c"];
422
423 metadata.push_back ("Title");
424 metadata.push_back ("classifytype");
425 metadata.push_back ("archivedir");
426
427 if (!arg_d.empty()) {
428 // we're at document level
429 text_t javaimagescontent;
430
431 // get metadata for this document and it's parents
432 if (get_info (arg_d, collection, metadata, true, collectproto, response, logout)) {
433 disp.setmacro ("header", "document", "_textheader_");
434
435 text_t pagetitle;
436 if (args.getintarg("gt") == 2)
437 pagetitle = *(response.docInfo[0].metadata[0].values.begin());
438 else {
439 text_tarray::const_iterator this_title = response.docInfo[0].metadata[0].values.begin();
440 text_tarray::const_iterator end_title = response.docInfo[0].metadata[0].values.end();
441 while (this_title != end_title) {
442 if ((this_title + 1) == end_title) pagetitle += *this_title;
443 else pagetitle += *this_title + ": ";
444 this_title ++;
445 }
446 }
447 disp.setmacro ("pagetitle", "document", pagetitle);
448 disp.setmacro ("thisOID", "Global", response.docInfo[0].metadata[2].values[0]);
449
450 text_t &classifytype = response.docInfo[0].metadata[1].values[0];
451 if (classifytype.empty()) classifytype = "Book"; // defaults to Book
452 if ((classifytype == "Book") || (classifytype == "Hierarchy"))
453 set_arrow_macros (arg_d, classifytype, disp, collectproto, collection, logout);
454
455 if (args["u"] != "1") {
456 javaimagescontent += "_javadetach_";
457 if (args["gt"] == "1")
458 javaimagescontent += "_javacontracttext__javacontinue_";
459 else
460 javaimagescontent += "_javaexpandtext_";
461 if (classifytype == "Hierarchy")
462 if (args["gc"] == "1")
463 javaimagescontent += "_javacontractcontents_";
464 else
465 javaimagescontent += "_javaexpandcontents_";
466 if (args["hl"] != "1")
467 javaimagescontent += "_javahighlighting_";
468 else
469 javaimagescontent += "_javanohighlighting_";
470 disp.setmacro ("javaimagescontent", "document", javaimagescontent);
471 }
472 }
473 } else {
474 if (!arg_cl.empty()) {
475
476 // get metadata for top level classification
477 text_t classtop;
478 get_top (arg_cl, classtop);
479 if (get_info (classtop, collection, metadata, false, collectproto, response, logout)) {
480
481 text_t &title = response.docInfo[0].metadata[0].values[0];
482 text_t &classifytype = response.docInfo[0].metadata[1].values[0];
483
484 disp.setmacro ("pagetitle", "document", "_text" + title + "page_");
485
486 disp.setmacro ("imagethispage", "document", "_icon" + title + "page_");
487
488 // now get the metadata for each child of top level
489 // so we can generate the _classificationlinks_ and arrow macros
490 // (if they're required by the current classification type)
491
492 if ((classifytype == "AZList") || (classifytype == "Datelist")) {
493
494 text_t classificationlinks, navarrows;
495 text_t link = "<a href=\"_httpdocument_&cl=";
496
497 metadata.erase(metadata.begin(), metadata.end());
498 metadata.push_back ("Title");
499 metadata.push_back ("doctype");
500 if (get_children (classtop, collection, metadata, collectproto, response, logout)) {
501
502 // don't want links unless there are 2 or more sections
503 if (response.docInfo.size() >= 2) {
504
505 classificationlinks += "<!-- Classification Links -->\n";
506 classificationlinks += "<table width=_pagewidth_ cellpadding=0 cellspacing=0 border=0>\n";
507 classificationlinks += "<tr><td valign=top><center>\n";
508
509 ResultDocInfo_tarray::const_iterator sechere = response.docInfo.begin();
510 ResultDocInfo_tarray::const_iterator secend = response.docInfo.end();
511
512 while (sechere != secend) {
513 if ((*sechere).metadata[1].values[0] == "classify") {
514 if (((*sechere).OID == arg_cl) || is_child_of((*sechere).OID, arg_cl)) {
515
516 // set the _httpprevarrow_, _httpnextarrow_ macros while we're here
517 if (sechere != response.docInfo.begin())
518 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&cl=" + (*(sechere-1)).OID);
519 if ((sechere + 1) != secend)
520 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&cl=" + (*(sechere+1)).OID);
521
522 classificationlinks += "\n<b>" + (*sechere).metadata[0].values[0] + "</b>&nbsp;&nbsp;&nbsp;";
523 } else {
524 classificationlinks += link + (*sechere).OID + "\">";
525 classificationlinks += (*sechere).metadata[0].values[0] + "</a>";
526 if ((sechere + 1) != secend) classificationlinks += "&nbsp;&nbsp;&nbsp;";
527 }
528 }
529 sechere ++;
530 }
531
532 classificationlinks += "\n</center></td></tr></table>\n";
533 classificationlinks += "<!-- End of Classification Links -->\n";
534
535 disp.setmacro ("classificationlinks", "document", classificationlinks);
536 }
537 }
538 }
539 }
540 }
541 }
542}
543
544bool documentaction::do_action (cgiargsclass &args, recptproto *collectproto,
545 displayclass &disp, outconvertclass &outconvert,
546 ostream &textout, ostream &logout) {
547
548 if (collectproto == NULL) {
549 logout << "documentaction::do_action called with NULL collectproto\n";
550 textout << outconvert << disp << "_document:header_\n"
551 << "Error: Attempt to get document without setting collection\n"
552 << "_document:footer_\n";
553 } else {
554
555 text_tarray metadata;
556 FilterResponse_t response;
557 text_t toptitle, toptype, thistype;
558
559 text_t &arg_d = args["d"];
560 text_t &arg_cl = args["cl"];
561
562 text_t OID = arg_d;
563 if (arg_d.empty()) OID = arg_cl;
564
565 textout << outconvert << disp << "_document:header_\n"
566 << "_document:content_\n";
567
568 if (arg_d.empty() && arg_cl.empty()) {
569 textout << outconvert << disp << "Document contains no data_document:footer_\n";
570 return true;
571 }
572
573 // get the classifytitle and classifytype for both the top level
574 // and the current level (using getParent=true)
575 metadata.push_back ("Title");
576 metadata.push_back ("classifytype");
577 if (get_info (OID, args["c"], metadata, true, collectproto, response, logout)) {
578 toptitle = response.docInfo[0].metadata[0].values[0];
579 toptype = response.docInfo[0].metadata[1].values[0];
580 thistype = response.docInfo[0].metadata[1].values.back();
581 }
582
583 // output the table of contents
584 if (!arg_d.empty()) {
585
586 if (toptype == "Hierarchy")
587 hierarchy_toc (thistype, toptitle, args, collectproto,
588 disp, outconvert, textout, logout);
589 else
590 // Book is the default for a document level toc - AZList, List and
591 // Datelist don't make sense for document level
592 book_toc (toptitle, args, collectproto, disp,
593 outconvert, textout, logout);
594 } else {
595
596 if (toptype == "Hierarchy")
597 hierarchy_toc (thistype, toptitle, args, collectproto,
598 disp, outconvert, textout, logout);
599 else if (toptype == "Datelist")
600 datelist_toc (thistype, toptitle, args, collectproto,
601 disp, outconvert, textout, logout);
602 else if (toptype == "AZList")
603 azlist_toc (thistype, toptitle, args, collectproto,
604 disp, outconvert, textout, logout);
605 else
606 // List is the default for a classification level toc - Book doesn't make
607 // sense for classification level
608 list_toc (thistype, toptitle, args, collectproto,
609 disp, outconvert, textout, logout);
610 }
611
612 // output the document text
613 output_document (OID, args, collectproto, disp, outconvert, textout, logout);
614
615 textout << outconvert << disp << "_document:footer_\n";
616 }
617 return true;
618}
619
620
621void documentaction::output_document (const text_t &OID, cgiargsclass &args,
622 recptproto *collectproto, displayclass &disp,
623 outconvertclass &outconvert, ostream &textout,
624 ostream &logout) {
625 FilterResponse_t inforesponse;
626 DocumentRequest_t docrequest;
627 DocumentResponse_t docresponse;
628 FilterResponse_t queryresponse;
629 comerror_t err;
630 text_tarray metadata;
631 bool highlight = false;
632 int arg_gt = args.getintarg("gt");
633 text_t &collection = args["c"];
634
635 // if we have a query string and highlighting is turned on we need
636 // to redo the query to get the terms for highlighting
637 if (!args["q"].empty() && args.getintarg("hl")) {
638 FilterRequest_t request;
639 request.filterResultOptions = FRmatchTerms;
640 text_t quotedquery; // not used
641 if (do_query (request, args, collectproto, quotedquery, queryresponse, logout))
642 highlight = true;
643 }
644
645 // get info on this document
646 metadata.push_back("Title");
647 metadata.push_back("hastxt");
648 metadata.push_back("haschildren");
649
650 if (get_info (OID, collection, metadata, false, collectproto, inforesponse, logout)) {
651 text_t title = inforesponse.docInfo[0].metadata[0].values[0];
652 int hastxt = inforesponse.docInfo[0].metadata[1].values[0].getint();
653 int haschildren = inforesponse.docInfo[0].metadata[2].values[0].getint();
654
655 if (arg_gt == 0) {
656 if (hastxt == 1) {
657 // get the text
658 docrequest.OID = OID;
659 collectproto->get_document (collection, docrequest, docresponse, err, logout);
660
661 textout << outconvert << disp << "<p>\n<h3>" << title << "</h3>";
662 if (highlight)
663 highlighttext(docresponse.doc, queryresponse.termInfo, disp,
664 outconvert, textout, logout);
665 else
666 textout << outconvert << disp << docresponse.doc;
667 }
668 } else {
669
670 // text is to be expanded
671 text_t exOID = OID;
672 if (!haschildren) exOID = get_parent (OID);
673
674 // if we're not in a document (i.e. we're in a top level classification)
675 // we need to pass the "classify" string to get_contents so that it
676 // doesn't recurse all the way through each document in the classification
677 text_t classifytype;
678 if (args["d"].empty()) classifytype = "classify";
679
680 int i; // not used
681 get_contents (exOID, classifytype, i, collection, collectproto, inforesponse, logout);
682
683 ResultDocInfo_tarray::const_iterator sechere = inforesponse.docInfo.begin();
684 ResultDocInfo_tarray::const_iterator secend = inforesponse.docInfo.end();
685
686 if (arg_gt == 1) {
687 // check if there are more than 10 sections containing text to be expanded -
688 // if there are output warning message - this isn't a great way to do this
689 // since the sections may be very large or very small - one day I'll fix it
690 // -- Stefan.
691 int seccount = 0;
692 while (sechere != secend) {
693 if ((*sechere).metadata[3].values[0] == "1") seccount ++;
694 if (seccount > 10) break;
695 sechere ++;
696 }
697 if (seccount > 10) {
698 // more than 10 sections so output warning message and text
699 // for current section only
700 textout << outconvert << disp << "_document:textltwarning_";
701 docrequest.OID = OID;
702 collectproto->get_document (collection, docrequest, docresponse, err, logout);
703
704 textout << outconvert << disp << "<p>\n<h3>" << title << "</h3>";
705 if (highlight)
706 highlighttext(docresponse.doc, queryresponse.termInfo, disp,
707 outconvert, textout, logout);
708 else
709 textout << outconvert << disp << docresponse.doc;
710 }
711 else arg_gt = 2;
712 }
713
714 if (arg_gt == 2) {
715 // get the text for each section
716 sechere = inforesponse.docInfo.begin();
717 int count = 0;
718 while (sechere != secend) {
719 textout << outconvert << disp << "\n<p><a name=" << count << "><h3>"
720 << (*sechere).metadata[0].values[0] << "</h3></a>\n";
721 if ((*sechere).metadata[3].values[0] == "1") {
722 docrequest.OID = (*sechere).OID;
723 collectproto->get_document (collection, docrequest, docresponse, err, logout);
724 if (highlight)
725 highlighttext(docresponse.doc, queryresponse.termInfo, disp,
726 outconvert, textout, logout);
727 else
728 textout << outconvert << disp << docresponse.doc;
729 }
730 count ++;
731 sechere ++;
732 }
733 }
734 }
735 }
736}
737
738// highlighttext highlights query terms in text string and outputs the resulting text string
739void documentaction::highlighttext(text_t &text, TermInfo_tarray &terms, displayclass &disp,
740 outconvertclass &outconvert, ostream &textout, ostream &/*logout*/) {
741
742 text_tmap allterms;
743 text_tmap::const_iterator it;
744
745 // first load all the term variations into a map
746 TermInfo_tarray::const_iterator this_term = terms.begin();
747 TermInfo_tarray::const_iterator last_term = terms.end();
748 while (this_term != last_term) {
749 text_tarray::const_iterator this_var = (*this_term).matchTerms.begin();
750 text_tarray::const_iterator last_var = (*this_term).matchTerms.end();
751 while (this_var != last_var) {
752 allterms[*this_var] = 1;
753 this_var ++;
754 }
755 this_term ++;
756 }
757
758 // get the text to start and end a hightlight
759 text_t starthighlight = "<b><u>";
760 text_t endhighlight = "</u></b>";
761 if (disp.isdefaultmacro("Global", "starthighlight"))
762 disp.expandstring("Global", "_starthighlight_", starthighlight);
763 if (disp.isdefaultmacro("Global", "endhighlight"))
764 disp.expandstring("Global", "_endhighlight_", endhighlight);
765
766
767 text_t::iterator here = text.begin();
768 text_t::iterator end = text.end();
769 text_t word, buffer;
770 while (here != end) {
771 if (is_unicode_letdig(*here)) {
772 // not word boundary
773 word.push_back(*here);
774 here++;
775
776 } else {
777 // found word boundary
778 // add last word if there was one
779 if (!word.empty()) {
780 it = allterms.find(word);
781 if (it != allterms.end()) {
782 word = starthighlight + word + endhighlight;
783 }
784 buffer += word;
785 word.clear();
786 }
787
788 if (*here == '<') {
789 // skip over rest of html tag
790 while ((here != end) && (*here != '>')) {
791 buffer.push_back(*here);
792 here++;
793 }
794 }
795
796 buffer.push_back(*here);
797 here++;
798
799 if (buffer.size() > 1024) {
800 textout << outconvert << disp << buffer;
801 buffer.clear();
802 }
803 }
804 }
805 textout << outconvert << disp << buffer;
806}
Note: See TracBrowser for help on using the repository browser.