source: trunk/gsdl/src/recpt/formattools.cpp@ 1941

Last change on this file since 1941 was 1941, checked in by jmt14, 23 years ago

Modified files:

browsetools.cpp documentaction.cpp formattools.cpp
formattools.h

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 25.6 KB
Line 
1/**********************************************************************
2 *
3 * formattools.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 *********************************************************************/
25
26#include "formattools.h"
27#include "cgiutils.h"
28#include "OIDtools.h"
29
30#include <assert.h>
31
32// a few function prototypes
33static text_t format_string (const text_t& collection, recptproto* collectproto,
34 ResultDocInfo_t &docinfo, displayclass &disp,
35 format_t *formatlistptr,
36 const text_t &link, const text_t &icon,
37 const text_t &text, bool highlight, ostream& logout);
38
39static bool parse_action (text_t::const_iterator &here, const text_t::const_iterator &end,
40 format_t *formatlistptr, text_tset &metadata, bool &getParents);
41
42void metadata_t::clear() {
43 metaname.clear();
44 metacommand = mNone;
45 parentcommand = pNone;
46 parentoptions.clear();
47}
48
49void decision_t::clear() {
50 command = dMeta;
51 meta.clear();
52 text.clear();
53}
54
55void format_t::clear() {
56 command = comText;
57 decision.clear();
58 text.clear();
59 meta.clear();
60 nextptr = NULL;
61 ifptr = NULL;
62 elseptr = NULL;
63 orptr = NULL;
64}
65
66void formatinfo_t::clear() {
67 DocumentImages = false;
68 DocumentTitles = true;
69 DocumentHeading = "{Or}{[parent(Top):Title],[Title],untitled}<br>";
70 DocumentContents = true;
71 DocumentArrowsBottom = true;
72 DocumentButtons.erase (DocumentButtons.begin(), DocumentButtons.end());
73 // DocumentButtons.push_back ("Expand Text");
74 // DocumentButtons.push_back ("Expand Contents");
75 DocumentButtons.push_back ("Detach");
76 DocumentButtons.push_back ("Highlight");
77 RelatedDocuments = "";
78 DocumentText = "<center><table width=_pagewidth_><tr><td>[Text]</td></tr></table></center>";
79 formatstrings.erase (formatstrings.begin(), formatstrings.end());
80 DocumentUseHTML = false;
81}
82
83// simply checks to see if formatstring begins with a <td> tag
84bool is_table_content (const text_t &formatstring) {
85 text_t::const_iterator here = formatstring.begin();
86 text_t::const_iterator end = formatstring.end();
87
88 while (here != end) {
89 if (*here != ' ') {
90 if ((*here == '<') && ((here+3) < end)) {
91 if ((*(here+1) == 't' || *(here+1) == 'T') &&
92 (*(here+2) == 'd' || *(here+2) == 'D') &&
93 (*(here+3) == '>' || *(here+3) == ' '))
94 return true;
95 } else return false;
96 }
97 here ++;
98 }
99 return false;
100}
101
102bool is_table_content (const format_t *formatlistptr) {
103
104 if (formatlistptr == NULL) return false;
105
106 if (formatlistptr->command == comText)
107 return is_table_content (formatlistptr->text);
108
109 return false;
110}
111
112// returns false if key isn't in formatstringmap
113bool get_formatstring (const text_t &key, const text_tmap &formatstringmap,
114 text_t &formatstring) {
115
116 formatstring.clear();
117 text_tmap::const_iterator it = formatstringmap.find(key);
118 if (it == formatstringmap.end()) return false;
119 formatstring = (*it).second;
120 return true;
121}
122
123// tries to find "key1key2" then "key1" then "key2"
124bool get_formatstring (const text_t &key1, const text_t &key2,
125 const text_tmap &formatstringmap,
126 text_t &formatstring) {
127
128 formatstring.clear();
129 text_tmap::const_iterator it = formatstringmap.find(key1 + key2);
130 if (it != formatstringmap.end()) {
131 formatstring = (*it).second;
132 return true;
133 }
134 it = formatstringmap.find(key1);
135 if (it != formatstringmap.end()) {
136 formatstring = (*it).second;
137 return true;
138 }
139 it = formatstringmap.find(key2);
140 if (it != formatstringmap.end()) {
141 formatstring = (*it).second;
142 return true;
143 }
144 return false;
145}
146
147
148// returns a date of form 31 _textmonthnn_ 1999
149// input is date of type 19991231
150// at least the year must be present in date
151text_t format_date (const text_t &date) {
152
153 if (date.size() < 4) return "";
154
155 text_t::const_iterator datebegin = date.begin();
156
157 text_t year = substr (datebegin, datebegin+4);
158
159 if (date.size() < 6) return year;
160
161 text_t month = "_textmonth" + substr (datebegin+4, datebegin+6) + "_";
162 int imonth = month.getint();
163 if (imonth < 0 || imonth > 12) return year;
164
165 if (date.size() < 8) return month + " " + year;
166
167 text_t day = substr (datebegin+6, datebegin+8);
168 if (day[0] == '0') day = substr (day.begin()+1, day.end());
169 int iday = day.getint();
170 if (iday < 0 || iday > 31) return month + " " + year;
171
172 return day + " " + month + " " + year;
173}
174
175
176//this function gets the information associated with the relation
177//metadata for the document associated with 'docinfo'. This relation
178//metadata consists of a line of pairs containing 'collection, document OID'
179//(this is the OID of the document related to the current document, and
180//the collection the related document belongs to). For each of these pairs
181//the title metadata is obtained and then an html link between the title
182//of the related doc and the document's position (the document will be
183//found in "<a href=\"_httpdocument_&c=collection&cl=search&d=OID">
184//(where collection is the related documents collection, and OID is the
185//related documents OID). A list of these html links are made for as many
186//related documents as there are. This list is then returned. If there are
187//no related documents available for the current document then the string
188//'.. no related documents .. ' is returned.
189text_t get_related_docs(const text_t& collection, recptproto* collectproto,
190 ResultDocInfo_t &docinfo, ostream& logout){
191
192 text_tset metadata;
193
194 //insert the metadata we wish to collect
195 metadata.insert("relation");
196 metadata.insert("Title");
197 metadata.insert("Subject"); //for emails, where title data doesn't apply
198
199 FilterResponse_t response;
200 text_t relation = ""; //string for displaying relation metadata
201 text_t relationTitle = ""; //the related documents Title (or subject)
202 text_t &relationOID = ""; //the related documents OID
203
204 //get the information associated with the metadata for current doc
205 if (get_info (docinfo.OID, collection, metadata,
206 false, collectproto, response, logout)) {
207
208 //if the relation metadata exists, store for displaying
209 if(!response.docInfo[0].metadata["relation"].values.empty()){
210 relationOID += response.docInfo[0].metadata["relation"].values[0];
211
212 //split relation data into pairs of collectionname,ID number
213 text_tarray relationpairs;
214 splitchar (relationOID.begin(), relationOID.end(), ' ', relationpairs);
215
216 text_tarray::const_iterator currDoc = relationpairs.begin();
217 text_tarray::const_iterator lastDoc = relationpairs.end();
218
219 //iterate through the pairs to split and display
220 while(currDoc != lastDoc){
221
222 //split pairs into collectionname and ID
223 text_tarray relationdata;
224 splitchar ((*currDoc).begin(), (*currDoc).end(), ',', relationdata);
225
226 //get first element in the array (collection)
227 text_tarray::const_iterator doc_data = relationdata.begin();
228 text_t document_collection = *doc_data;
229 doc_data++; //increment to get next item in array (oid)
230 text_t document_OID = *doc_data;
231
232 //create html link to related document
233 relation += "<a href=\"_httpdocument_&c=" + document_collection;
234 relation += "&cl=search&d=" + document_OID;
235
236 //get the information associated with the metadata for related doc
237 if (get_info (document_OID, document_collection, metadata,
238 false, collectproto, response, logout)) {
239
240 //if title metadata doesn't exist, collect subject metadata
241 //if that doesn't exist, just call it 'related document'
242 if (!response.docInfo[0].metadata["Title"].values[0].empty())
243 relationTitle = response.docInfo[0].metadata["Title"].values[0];
244 else if (!response.docInfo[0].metadata["Subject"].values.empty())
245 relationTitle = response.docInfo[0].metadata["Subject"].values[0];
246 else relationTitle = "RELATED DOCUMENT";
247
248 }
249
250 //link the related document's title to its page
251 relation += "\">" + relationTitle + "</a>";
252 relation += " (" + document_collection + ")<br>";
253
254 currDoc++;
255 }
256 }
257
258 }
259
260 if(relation.empty()) //no relation data for documnet
261 relation = ".. no related documents .. ";
262
263 return relation;
264}
265
266
267
268static void get_parent_options (text_t &instring, metadata_t &metaoption) {
269
270 assert (instring.size() > 7);
271 if (instring.size() <= 7) return;
272
273 text_t meta, com, op;
274 bool inbraces = false;
275 bool inquotes = false;
276 bool foundcolon = false;
277 text_t::const_iterator here = instring.begin()+6;
278 text_t::const_iterator end = instring.end();
279 while (here != end) {
280 if (*here == '(') inbraces = true;
281 else if (*here == ')') inbraces = false;
282 else if (*here == '\'' && !inquotes) inquotes = true;
283 else if (*here == '\'' && inquotes) inquotes = false;
284 else if (*here == ':' && !inbraces) foundcolon = true;
285 else if (foundcolon) meta.push_back (*here);
286 else if (inquotes) op.push_back (*here);
287 else com.push_back (*here);
288 here ++;
289 }
290 instring = meta;
291 if (com.empty())
292 metaoption.parentcommand = pImmediate;
293 else if (com == "Top")
294 metaoption.parentcommand = pTop;
295 else if (com == "All") {
296 metaoption.parentcommand = pAll;
297 metaoption.parentoptions = op;
298 }
299}
300
301static void parse_meta (text_t &meta, metadata_t &metaoption,
302 text_tset &metadata, bool &getParents) {
303
304 if (meta.size() > 8 && (substr(meta.begin(), meta.begin()+8) == "cgisafe:")) {
305 metaoption.metacommand = mCgiSafe;
306 meta = substr (meta.begin()+8, meta.end());
307 }
308
309 if (meta.size() > 7 && (substr (meta.begin(), meta.begin()+6) == "parent")) {
310 getParents = true;
311 get_parent_options (meta, metaoption);
312 }
313
314 metadata.insert (meta);
315 metaoption.metaname = meta;
316}
317
318static void parse_meta (text_t &meta, format_t *formatlistptr,
319 text_tset &metadata, bool &getParents) {
320
321 if (meta == "link")
322 formatlistptr->command = comLink;
323 else if (meta == "/link")
324 formatlistptr->command = comEndLink;
325
326 else if (meta == "num")
327 formatlistptr->command = comNum;
328
329 else if (meta == "icon")
330 formatlistptr->command = comIcon;
331
332 else if (meta == "Text")
333 formatlistptr->command = comDoc;
334
335 else if (meta == "RelatedDocuments")
336 formatlistptr->command = comRel;
337
338 else if (meta == "highlight")
339 formatlistptr->command = comHighlight;
340
341 else if (meta == "/highlight")
342 formatlistptr->command = comEndHighlight;
343
344 else {
345 formatlistptr->command = comMeta;
346 parse_meta (meta, formatlistptr->meta, metadata, getParents);
347 }
348}
349
350static bool parse_string (const text_t &formatstring, format_t *formatlistptr,
351 text_tset &metadata, bool &getParents) {
352
353 text_t text;
354 text_t::const_iterator here = formatstring.begin();
355 text_t::const_iterator end = formatstring.end();
356
357 while (here != end) {
358
359 if (*here == '\\') {
360 here ++;
361 if (here != end) text.push_back (*here);
362
363 } else if (*here == '{') {
364 if (!text.empty()) {
365 formatlistptr->command = comText;
366 formatlistptr->text = text;
367 formatlistptr->nextptr = new format_t();
368 formatlistptr = formatlistptr->nextptr;
369
370 text.clear();
371 }
372 if (parse_action (++here, end, formatlistptr, metadata, getParents)) {
373
374 formatlistptr->nextptr = new format_t();
375 formatlistptr = formatlistptr->nextptr;
376 if (here == end) break;
377 }
378 } else if (*here == '[') {
379 if (!text.empty()) {
380 formatlistptr->command = comText;
381 formatlistptr->text = text;
382 formatlistptr->nextptr = new format_t();
383 formatlistptr = formatlistptr->nextptr;
384
385 text.clear();
386 }
387 text_t meta;
388 here ++;
389 while (*here != ']') {
390 if (here == end) return false;
391 meta.push_back (*here);
392 here ++;
393 }
394 parse_meta (meta, formatlistptr, metadata, getParents);
395 formatlistptr->nextptr = new format_t();
396 formatlistptr = formatlistptr->nextptr;
397
398 } else
399 text.push_back (*here);
400
401 if (here != end) here ++;
402 }
403 if (!text.empty()) {
404 formatlistptr->command = comText;
405 formatlistptr->text = text;
406 formatlistptr->nextptr = new format_t();
407 formatlistptr = formatlistptr->nextptr;
408
409 }
410 return true;
411}
412
413
414static bool parse_action (text_t::const_iterator &here, const text_t::const_iterator &end,
415 format_t *formatlistptr, text_tset &metadata, bool &getParents) {
416
417 text_t::const_iterator it = findchar (here, end, '}');
418 if (it == end) return false;
419
420 text_t com = substr (here, it);
421 here = findchar (it, end, '{');
422 if (here == end) return false;
423 else here ++;
424
425 if (com == "If") formatlistptr->command = comIf;
426 else if (com == "Or") formatlistptr->command = comOr;
427 else return false;
428
429 int commacount = 0;
430 text_t text;
431 while (here != end) {
432
433 if (*here == '\\') {
434 here++;
435 if (here != end) text.push_back(*here);
436
437 }
438
439 else if (*here == ',' || *here == '}' || *here == '{') {
440
441 if (formatlistptr->command == comOr) {
442 // the {Or}{this, or this, or this, or this} statement
443 format_t *or_ptr;
444
445 // find the next unused orptr
446 if (formatlistptr->orptr == NULL) {
447 formatlistptr->orptr = new format_t();
448 or_ptr = formatlistptr->orptr;
449 } else {
450 or_ptr = formatlistptr->orptr;
451 while (or_ptr->nextptr != NULL)
452 or_ptr = or_ptr->nextptr;
453 or_ptr->nextptr = new format_t();
454 or_ptr = or_ptr->nextptr;
455 }
456
457 if (!text.empty())
458 {
459 if (!parse_string(text, or_ptr, metadata, getParents)) { return false; }
460 }
461
462 if (*here == '{')
463 {
464 // Supports: {Or}{[Booktitle],[Title],{If}{[XXXX],aaa,bbb}}
465 // but not : {Or}{[Booktitle],[Title]{If}{[XXXX],aaa,bbb}}
466 // The latter can always be re-written:
467 // {Or}{[Booktitle],{If}{[Title],[Title]{If}{[XXXX],aaa,bbb}}}
468
469 if (!text.empty()) // already used up allocated format_t
470 {
471 // => allocate new one for detected action
472 or_ptr->nextptr = new format_t();
473 or_ptr = or_ptr->nextptr;
474 }
475 if (!parse_action(++here, end, or_ptr, metadata, getParents))
476 {
477 return false;
478 }
479 }
480 else
481 {
482 if (*here == '}') break;
483 }
484 text.clear();
485
486 }
487
488 // Parse an {If}{decide,do,else} statement
489 else {
490
491 // Read the decision component.
492 if (commacount == 0) {
493 // Decsion can be a metadata element, or a piece of text.
494 // Originally Stefan's code, updated 25/10/2000 by Gordon.
495
496 text_t::const_iterator beginbracket = text.begin();
497 text_t::const_iterator endbracket = (text.end() - 1);
498
499 // Decision is based on a metadata element
500 if ((*beginbracket == '[') && (*endbracket == ']')) {
501 // Ignore the surrounding square brackets
502 text_t meta = substr (beginbracket+1, endbracket);
503 parse_meta (meta, formatlistptr->decision.meta, metadata, getParents);
504 commacount ++;
505 text.clear();
506 }
507
508 // Decision is a piece of text (probably a macro like _cgiargmode_).
509 else {
510 formatlistptr->decision.command = dText;
511 formatlistptr->decision.text = text;
512 commacount ++;
513 text.clear();
514 }
515 }
516
517 // Read the "then" and "else" components of the {If} statement.
518 else {
519 format_t** nextlistptr = NULL;
520 if (commacount == 1) {
521 nextlistptr = &formatlistptr->ifptr;
522 } else if (commacount == 2 ) {
523 nextlistptr = &formatlistptr->elseptr;
524 } else {
525 return false;
526 }
527
528 if (!text.empty()) {
529 if (*nextlistptr == NULL) {
530 *nextlistptr = new format_t();
531 } else {
532
533 // skip to the end of any format_t statements already added
534 while ((*nextlistptr)->nextptr != NULL)
535 {
536 nextlistptr = &(*nextlistptr)->nextptr;
537 }
538
539 (*nextlistptr)->nextptr = new format_t();
540 nextlistptr = &(*nextlistptr)->nextptr;
541 }
542
543 if (!parse_string (text, *nextlistptr, metadata, getParents))
544 {
545 return false;
546 }
547 text.clear();
548 }
549
550 if (*here == '{')
551 {
552 if (*nextlistptr == NULL) {
553 *nextlistptr = new format_t();
554 } else {
555 (*nextlistptr)->nextptr = new format_t();
556 nextlistptr = &(*nextlistptr)->nextptr;
557 }
558
559 if (!parse_action(++here, end, *nextlistptr, metadata, getParents))
560 {
561 return false;
562 }
563 }
564 else
565 {
566 if (*here == '}') break;
567 commacount ++;
568 }
569 }
570 }
571
572 } else text.push_back(*here);
573
574 if (here != end) here ++;
575 }
576
577 return true;
578}
579
580
581bool parse_formatstring (const text_t &formatstring, format_t *formatlistptr,
582 text_tset &metadata, bool &getParents) {
583
584 formatlistptr->clear();
585 getParents = false;
586
587 return (parse_string (formatstring, formatlistptr, metadata, getParents));
588}
589
590
591// note: all the format_date stuff is assuming that all Date metadata is going to
592// be of the form yyyymmdd, this is of course, crap ;)
593
594static text_t get_meta (ResultDocInfo_t &docinfo, const metadata_t &meta) {
595
596 // make sure we have the requested metadata
597 MetadataInfo_tmap::iterator it = docinfo.metadata.find (meta.metaname);
598 if (it == docinfo.metadata.end()) return "";
599
600 MetadataInfo_t *parent = docinfo.metadata[meta.metaname].parent;
601
602 switch (meta.parentcommand) {
603 case pNone:
604 {
605 text_t classifier_metaname = docinfo.classifier_metadata_type;
606 int metaname_index
607 = (classifier_metaname == meta.metaname) ? docinfo.classifier_metadata_offset : 0;
608 text_t metadata_item = docinfo.metadata[meta.metaname].values[metaname_index];
609
610 if (meta.metaname == "Date")
611 return format_date (metadata_item);
612 if (meta.metacommand == mCgiSafe)
613 return cgi_safe (metadata_item);
614 else return metadata_item;
615 }
616
617 case pImmediate:
618 if (parent != NULL) {
619 if (meta.metaname == "Date")
620 return format_date (parent->values[0]);
621 if (meta.metacommand == mCgiSafe)
622 return cgi_safe (parent->values[0]);
623 else return parent->values[0];
624 }
625 break;
626
627 case pTop:
628 if (parent != NULL) {
629 while (parent->parent != NULL) parent = parent->parent;
630
631 if (meta.metaname == "Date")
632 return format_date (parent->values[0]);
633 if (meta.metacommand == mCgiSafe)
634 return cgi_safe (parent->values[0]);
635 else return parent->values[0];
636 }
637 break;
638
639 case pAll:
640 MetadataInfo_t *parent = docinfo.metadata[meta.metaname].parent;
641 if (parent != NULL) {
642 text_tarray tmparray;
643 while (parent != NULL) {
644 tmparray.push_back (parent->values[0]);
645 parent = parent->parent;
646 }
647 bool first = true;
648 text_t tmp;
649 text_tarray::reverse_iterator here = tmparray.rbegin();
650 text_tarray::reverse_iterator end = tmparray.rend();
651 while (here != end) {
652 if (!first) tmp += meta.parentoptions;
653 if (meta.metaname == "Date") tmp += format_date (*here);
654 else tmp += *here;
655 first = false;
656 here ++;
657 }
658 if (meta.metacommand == mCgiSafe) return cgi_safe (tmp);
659 else return tmp;
660 }
661 }
662 return "";
663}
664
665static text_t get_or (const text_t& collection, recptproto* collectproto,
666 ResultDocInfo_t &docinfo, displayclass &disp,
667 format_t *orptr,
668 const text_t &link, const text_t &icon,
669 const text_t &text, bool highlight,
670 ostream& logout) {
671
672 text_t tmp;
673 while (orptr != NULL) {
674
675 tmp = format_string (collection,collectproto, docinfo, disp, orptr,
676 link, icon, text, highlight, logout);
677 if (!tmp.empty()) return tmp;
678
679 orptr = orptr->nextptr;
680 }
681 return "";
682}
683
684static text_t get_if (const text_t& collection, recptproto* collectproto,
685 ResultDocInfo_t &docinfo, displayclass &disp,
686 const decision_t &decision,
687 format_t *ifptr, format_t *elseptr, const text_t &link,
688 const text_t &icon, const text_t &text, bool highlight,
689 ostream& logout)
690{
691
692 // If the decision component is a metadata element, then evaluate it
693 // to see whether we output the "then" or the "else" clause
694 if (decision.command == dMeta) {
695 if (get_meta (docinfo, decision.meta) != "") {
696 if (ifptr != NULL)
697 return get_formatted_string (collection,collectproto, docinfo, disp, ifptr,
698 link, icon, text, highlight, logout);
699 }
700 else {
701 if (elseptr != NULL)
702 return get_formatted_string (collection,collectproto, docinfo, disp, elseptr,
703 link, icon, text, highlight, logout);
704 }
705 }
706
707 // If the decision component is text, then evaluate it (it is probably a
708 // macro like _cgiargmode_) to decide what to output.
709 else if (decision.command == dText) {
710
711 text_t outstring;
712 disp.expandstring (decision.text, outstring);
713
714 // This is a tad tricky. When we expand a string like _cgiargmode_, that is
715 // a cgi argument macro that has not been set, it evaluates to itself.
716 // Therefore, were have to say that a piece of text evalautes true if
717 // it is non-empty and if it is a cgi argument evaulating to itself.
718 if ((outstring != "") && !((outstring == decision.text) && (outstring[0] == '_'))) {
719 if (ifptr != NULL)
720 return get_formatted_string (collection, collectproto, docinfo, disp, ifptr,
721 link, icon, text, highlight, logout);
722 } else {
723 if (elseptr != NULL)
724 return get_formatted_string (collection, collectproto, docinfo, disp, elseptr,
725 link, icon, text, highlight, logout);
726 }
727 }
728
729 return "";
730}
731
732bool includes_metadata(const text_t& text)
733{
734 text_t::const_iterator here = text.begin();
735 text_t::const_iterator end = text.end();
736 while (here != end) {
737 if (*here == '[') return true;
738 here ++;
739 }
740
741 return false;
742}
743
744
745
746text_t format_string (const text_t& collection, recptproto* collectproto,
747 ResultDocInfo_t &docinfo, displayclass &disp,
748 format_t *formatlistptr,
749 const text_t &link, const text_t &icon,
750 const text_t &text, bool highlight,
751 ostream& logout) {
752
753 if (formatlistptr == NULL) return "";
754
755 switch (formatlistptr->command) {
756 case comText:
757 return formatlistptr->text;
758 case comLink:
759 return link;
760 case comEndLink:
761 if (link.empty()) return "";
762 else return "</a>";
763 case comIcon:
764 return icon;
765 case comNum:
766 return docinfo.result_num;
767 case comRel: //if [RelatedDocuments] appears in format string, collect relation data
768 return get_related_docs(collection, collectproto, docinfo, logout);
769 case comMeta:
770
771 {
772 const text_t& metavalue = get_meta (docinfo, formatlistptr->meta);
773
774 if (includes_metadata(metavalue))
775 {
776 // text has embedded metadata in it => expand it
777 FilterRequest_t request;
778 FilterResponse_t response;
779
780 request.getParents = false;
781
782 format_t *expanded_formatlistptr = new format_t();
783 parse_formatstring (metavalue, expanded_formatlistptr,
784 request.fields, request.getParents);
785
786 // retrieve metadata
787 get_info(docinfo.OID, collection, request.fields, request.getParents,
788 collectproto, response, logout);
789
790 if (!response.docInfo.empty())
791 {
792 text_t expanded_metavalue
793 = get_formatted_string(collection, collectproto,
794 response.docInfo[0], disp, expanded_formatlistptr,
795 link, icon, highlight, logout);
796
797 return expanded_metavalue;
798 }
799 else
800 {
801 return metavalue;
802 }
803 }
804 else
805 {
806 return metavalue;
807 }
808 }
809 case comDoc:
810 return text;
811 case comHighlight:
812 if (highlight) return "<b>";
813 break;
814 case comEndHighlight:
815 if (highlight) return "</b>";
816 break;
817 case comIf:
818 return get_if (collection, collectproto, docinfo, disp,
819 formatlistptr->decision, formatlistptr->ifptr,
820 formatlistptr->elseptr, link, icon, text, highlight,
821 logout);
822 case comOr:
823 return get_or (collection,collectproto, docinfo, disp, formatlistptr->orptr,
824 link, icon, text, highlight, logout);
825 }
826 return "";
827}
828
829
830
831
832text_t get_formatted_string (const text_t& collection, recptproto* collectproto,
833 ResultDocInfo_t& docinfo, displayclass &disp,
834 format_t* formatlistptr,
835 const text_t& link, const text_t& icon,
836 const text_t& text, const bool highlight,
837 ostream& logout) {
838
839 text_t ft;
840 while (formatlistptr != NULL)
841 {
842 ft += format_string (collection, collectproto, docinfo, disp, formatlistptr,
843 link, icon, text, highlight, logout);
844 formatlistptr = formatlistptr->nextptr;
845 }
846
847 return ft;
848}
849
850text_t get_formatted_string (const text_t& collection, recptproto* collectproto,
851 ResultDocInfo_t &docinfo, displayclass &disp,
852 format_t *formatlistptr,
853 const text_t &link, const text_t &icon,
854 const bool highlight,
855 ostream& logout) {
856
857 text_t text = "";
858
859 return get_formatted_string(collection, collectproto, docinfo, disp, formatlistptr,
860 link, icon, text, highlight, logout);
861}
862
863text_t get_formatted_string (const text_t& collection, recptproto* collectproto,
864 ResultDocInfo_t &docinfo, displayclass &disp,
865 format_t *formatlistptr,
866 const text_t& text,
867 ostream& logout) {
868
869 text_t link = "<a href=\"_httpdocument_&cl=search&d=" + docinfo.OID + "\">";
870 text_t icon = "_icontext_";
871 bool highlight = false;
872
873 return get_formatted_string(collection, collectproto, docinfo, disp, formatlistptr,
874 link, icon, text, highlight, logout);
875}
876
877text_t get_formatted_string (const text_t& collection, recptproto* collectproto,
878 ResultDocInfo_t &docinfo, displayclass &disp,
879 format_t *formatlistptr,
880 ostream& logout) {
881
882 text_t text = "";
883
884 return get_formatted_string(collection, collectproto, docinfo, disp, formatlistptr,
885 text, logout);
886}
887
888
889
890
891
892
893
Note: See TracBrowser for help on using the repository browser.