source: trunk/gsdl/src/recpt/queryaction.cpp@ 298

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

author is added to queryresults if there is one

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 14.7 KB
Line 
1/**********************************************************************
2 *
3 * queryaction.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * PUT COPYRIGHT NOTICE HERE
7 *
8 * $Id: queryaction.cpp 298 1999-06-27 22:02:11Z sjboddie $
9 *
10 *********************************************************************/
11
12/*
13 $Log$
14 Revision 1.8 1999/06/27 22:02:11 sjboddie
15 author is added to queryresults if there is one
16
17 Revision 1.7 1999/06/26 01:10:18 rjmcnab
18 Made h, i, and n arguments saved in the compressed arguments.
19
20 Revision 1.6 1999/06/24 05:12:25 sjboddie
21 lots of small changes
22
23 Revision 1.5 1999/06/16 04:03:48 sjboddie
24 Now sets "cl" arg to "search" when going to a document from a search
25 results page. This allows the close book icon (in hierarchy toc) to
26 take you back to the results page if that's where you came from.
27 If you got to the document page somehow other than from a
28 classification or a search (i.e. if "cl" isn't set) then the close
29 book icon is disabled
30
31 Revision 1.4 1999/06/16 02:08:38 sjboddie
32 got queryaction working
33
34 Revision 1.3 1999/03/25 03:06:45 sjboddie
35
36 altered receptionist slightly so it now passes *collectproto to
37 define_internal_macros and define_external_macros - need it
38 for browseaction
39
40 Revision 1.2 1999/03/03 20:26:50 rjmcnab
41
42 Modified stuff.
43
44 Revision 1.1 1999/02/28 22:45:21 rjmcnab
45
46 Initial revision.
47
48 */
49
50
51#include "queryaction.h"
52#include "querytools.h"
53
54queryaction::queryaction () {
55 // this action uses cgi variable "a"
56 cgiarginfo arg_ainfo;
57 arg_ainfo.shortname = "a";
58 arg_ainfo.longname = "action";
59 arg_ainfo.multiplechar = true;
60 arg_ainfo.defaultstatus = cgiarginfo::weak;
61 arg_ainfo.argdefault = "q";
62 arg_ainfo.savedarginfo = cgiarginfo::must;
63 argsinfo.addarginfo (NULL, arg_ainfo);
64
65 // "h"
66 arg_ainfo.shortname = "h";
67 arg_ainfo.longname = "main index";
68 arg_ainfo.multiplechar = true;
69 arg_ainfo.defaultstatus = cgiarginfo::weak;
70 arg_ainfo.argdefault = "";
71 arg_ainfo.savedarginfo = cgiarginfo::must;
72 argsinfo.addarginfo (NULL, arg_ainfo);
73
74 // "j"
75 arg_ainfo.shortname = "j";
76 arg_ainfo.longname = "sub collection index";
77 arg_ainfo.multiplechar = true;
78 arg_ainfo.defaultstatus = cgiarginfo::weak;
79 arg_ainfo.argdefault = "";
80 arg_ainfo.savedarginfo = cgiarginfo::must;
81 argsinfo.addarginfo (NULL, arg_ainfo);
82
83 // "n"
84 arg_ainfo.shortname = "n";
85 arg_ainfo.longname = "language index";
86 arg_ainfo.multiplechar = true;
87 arg_ainfo.defaultstatus = cgiarginfo::weak;
88 arg_ainfo.argdefault = "";
89 arg_ainfo.savedarginfo = cgiarginfo::must;
90 argsinfo.addarginfo (NULL, arg_ainfo);
91
92 // "q"
93 arg_ainfo.shortname = "q";
94 arg_ainfo.longname = "query string";
95 arg_ainfo.multiplechar = true;
96 arg_ainfo.defaultstatus = cgiarginfo::weak;
97 arg_ainfo.argdefault = "";
98 arg_ainfo.savedarginfo = cgiarginfo::must;
99 argsinfo.addarginfo (NULL, arg_ainfo);
100
101 // "t" - 1 = ranked 0 = boolean
102 arg_ainfo.shortname = "t";
103 arg_ainfo.longname = "search type";
104 arg_ainfo.multiplechar = false;
105 arg_ainfo.defaultstatus = cgiarginfo::weak;
106 arg_ainfo.argdefault = "1";
107 arg_ainfo.savedarginfo = cgiarginfo::must;
108 argsinfo.addarginfo (NULL, arg_ainfo);
109
110 // "k"
111 arg_ainfo.shortname = "k";
112 arg_ainfo.longname = "casefolding";
113 arg_ainfo.multiplechar = false;
114 arg_ainfo.defaultstatus = cgiarginfo::weak;
115 arg_ainfo.argdefault = "1";
116 arg_ainfo.savedarginfo = cgiarginfo::must;
117 argsinfo.addarginfo (NULL, arg_ainfo);
118
119 // "s"
120 arg_ainfo.shortname = "s";
121 arg_ainfo.longname = "stemming";
122 arg_ainfo.multiplechar = false;
123 arg_ainfo.defaultstatus = cgiarginfo::weak;
124 arg_ainfo.argdefault ="0";
125 arg_ainfo.savedarginfo = cgiarginfo::must;
126 argsinfo.addarginfo (NULL, arg_ainfo);
127
128 // "m"
129 arg_ainfo.shortname = "m";
130 arg_ainfo.longname = "maximum number of documents";
131 arg_ainfo.multiplechar = true;
132 arg_ainfo.defaultstatus = cgiarginfo::weak;
133 arg_ainfo.argdefault = "50";
134 arg_ainfo.savedarginfo = cgiarginfo::must;
135 argsinfo.addarginfo (NULL, arg_ainfo);
136
137 // "o"
138 arg_ainfo.shortname = "o";
139 arg_ainfo.longname = "hits per page";
140 arg_ainfo.multiplechar = true;
141 arg_ainfo.defaultstatus = cgiarginfo::weak;
142 arg_ainfo.argdefault = "20";
143 arg_ainfo.savedarginfo = cgiarginfo::must;
144 argsinfo.addarginfo (NULL, arg_ainfo);
145
146 // "r"
147 arg_ainfo.shortname = "r";
148 arg_ainfo.longname = "start results from";
149 arg_ainfo.multiplechar = true;
150 arg_ainfo.defaultstatus = cgiarginfo::weak;
151 arg_ainfo.argdefault = "1";
152 arg_ainfo.savedarginfo = cgiarginfo::must;
153 argsinfo.addarginfo (NULL, arg_ainfo);
154}
155
156void queryaction::configure (const text_t &key, const text_tarray &cfgline) {
157 action::configure (key, cfgline);
158}
159
160bool queryaction::init (ostream &logout) {
161 return action::init (logout);
162}
163
164bool queryaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
165 ostream &logout) {
166
167 // check t argument
168 int arg_t = args.getintarg("t");
169 if (arg_t != 0 && arg_t != 1) {
170 logout << "Warning: \"t\" argument out of range (" << arg_t << ")\n";
171 cgiarginfo *tinfo = argsinfo.getarginfo ("t");
172 if (tinfo != NULL) args["t"] = tinfo->argdefault;
173 }
174
175 // check k argument
176 int arg_k = args.getintarg("k");
177 if (arg_k != 0 && arg_k != 1) {
178 logout << "Warning: \"k\" argument out of range (" << arg_k << ")\n";
179 cgiarginfo *kinfo = argsinfo.getarginfo ("k");
180 if (kinfo != NULL) args["k"] = kinfo->argdefault;
181 }
182
183 // check s argument
184 int arg_s = args.getintarg("s");
185 if (arg_s != 0 && arg_s != 1) {
186 logout << "Warning: \"s\" argument out of range (" << arg_s << ")\n";
187 cgiarginfo *sinfo = argsinfo.getarginfo ("s");
188 if (sinfo != NULL) args["s"] = sinfo->argdefault;
189 }
190
191 // check m argument
192 int arg_m = args.getintarg("m");
193 if (arg_m < 0) {
194 logout << "Warning: \"m\" argument less than 0 (" << arg_m << ")\n";
195 cgiarginfo *minfo = argsinfo.getarginfo ("m");
196 if (minfo != NULL) args["m"] = minfo->argdefault;
197 }
198
199 // check o argument
200 int arg_o = args.getintarg("o");
201 if (arg_o < 0) {
202 logout << "Warning: \"o\" argument less than 0 (" << arg_o << ")\n";
203 cgiarginfo *oinfo = argsinfo.getarginfo ("o");
204 if (oinfo != NULL) args["o"] = oinfo->argdefault;
205 }
206
207 // check r argument
208 int arg_r = args.getintarg("r");
209 if (arg_r < 1) {
210 logout << "Warning: \"r\" argument less than 1 (" << arg_r << ")\n";
211 cgiarginfo *rinfo = argsinfo.getarginfo ("r");
212 if (rinfo != NULL) args["r"] = rinfo->argdefault;
213 }
214
215 return true;
216}
217
218void queryaction::get_cgihead_info (cgiargsclass &/*args*/, response_t &response,
219 text_t &response_data, ostream &/*logout*/) {
220 response = content;
221 response_data = "text/html";
222}
223
224void queryaction::define_internal_macros (displayclass &/*disp*/, cgiargsclass &/*args*/,
225 recptproto */*collectproto*/, ostream &/*logout*/) {
226
227 // define_internal_macros doesn't set anything for this action. The following
228 // macros are set later though in define_query_macros (they can't be set until
229 // the query has been done).
230
231 // _freqmsg_ the term frequency string
232
233 // _quotedquery_ the part of the query string that was quoted for post-processing
234
235 // _resultline_ the "x documents matched the query" string
236
237 // _prevfirst_ these are used when setting up the links to previous/next
238 // _prevlast_ pages of results (_thisfirst_ and _thislast_ are used to set
239 // _nextfirst_ the 'results x-x for query: xxxx' string in the title bar)
240 // _nextlast_
241 // _thisfirst_
242 // _thislast_
243
244}
245
246// sets the selection box macros _hselection_, _jselection_, and _nselection_.
247// each option will need an _optionxoption_ macro (i.e. an _hselection_ macro
248// with options stx and ptx will need _optionhstx_ and _optionhptx_ macros)
249void queryaction::set_option_macro (const text_t &macroname, text_t current_value,
250 const FilterOption_t &option, displayclass &disp) {
251
252 if (option.validValues.size() < 2) return;
253
254 text_t macrovalue = "<select name=\"" + macroname + "\">\n";
255
256 if (current_value.empty()) current_value = option.defaultValue;
257
258 text_tarray::const_iterator thisvalue = option.validValues.begin();
259 text_tarray::const_iterator endvalue = option.validValues.end();
260
261 while (thisvalue != endvalue) {
262 macrovalue += "<option value=\"" + *thisvalue + "\"";
263 if (*thisvalue == current_value)
264 macrovalue += " selected";
265 macrovalue += ">_option" + macroname + *thisvalue + "_\n";
266 thisvalue ++;
267 }
268 macrovalue += "</select>\n";
269 disp.setmacro (macroname + "selection", "Global", macrovalue);
270}
271
272void queryaction::define_external_macros (displayclass &disp, cgiargsclass &args,
273 recptproto *collectproto, ostream &logout) {
274
275 // define_external_macros sets the following macros:
276
277 // some or all of these may not be required to be set
278 // _hselection_ the selection box for the main part of the index
279 // _jselection_ the selection box for the subcollection part of the index
280 // _nselection_ the selection box for the language part of the index
281
282
283 // can't do anything if collectproto is null (i.e. no collection was specified)
284 if (collectproto == NULL) return;
285
286 comerror_t err;
287 InfoFilterOptionsResponse_t response;
288 InfoFilterOptionsRequest_t request;
289 request.filterName = "QueryFilter";
290
291 collectproto->get_filteroptions (args["c"], request, response, err, logout);
292 if (err == noError) {
293
294 FilterOption_tmap::const_iterator it;
295 FilterOption_tmap::const_iterator end = response.filterOptions.end();
296
297 // _hselection_ (Index)
298 it = response.filterOptions.find ("Index");
299 if (it != end) set_option_macro ("h", args["h"], (*it).second, disp);
300
301 // _jselection_ (Subcollection)
302 it = response.filterOptions.find ("Subcollection");
303 if (it != end) set_option_macro ("j", args["j"], (*it).second, disp);
304
305 // _nselection_ (Language)
306 it = response.filterOptions.find ("Language");
307 if (it != end) set_option_macro ("n", args["n"], (*it).second, disp);
308 }
309}
310
311bool queryaction::do_action (cgiargsclass &args, recptproto *collectproto,
312 displayclass &disp, outconvertclass &outconvert,
313 ostream &textout, ostream &logout) {
314
315 if (collectproto == NULL) {
316 logout << "queryaction::do_action called with NULL collectproto\n";
317 textout << outconvert << disp << "_query:header_\n"
318 << "Error: Attempt to do query without setting collection\n"
319 << "_query:footer_\n";
320 } else {
321
322 text_t quotedstring;
323 FilterResponse_t response;
324
325 // do the query
326 FilterRequest_t request;
327 request.filterResultOptions = FROID | FRmetadata | FRtermFreq;
328 request.fields.push_back ("Title");
329 request.fields.push_back ("Creator");
330 request.getParents = true;
331 if (!do_query (request, args, collectproto, quotedstring, response, logout))
332 return false;
333
334 // set macros
335 define_query_macros (args, disp, response, quotedstring);
336
337 // output the header
338 textout << outconvert << disp << "_query:header_\n_query:content_";
339
340 // output results
341 ResultDocInfo_tarray::const_iterator this_doc = response.docInfo.begin();
342 ResultDocInfo_tarray::const_iterator end_doc = response.docInfo.end();
343
344 textout << "<table cellspacing=4>\n";
345 while (this_doc != end_doc) {
346
347 text_t link = "<a href=\"_httpdocument_&cl=search&d=" + (*this_doc).OID + "\">";
348
349 text_t title;
350 text_tarray::const_iterator this_title = (*this_doc).metadata[0].values.begin();
351 text_tarray::const_iterator end_title = (*this_doc).metadata[0].values.end();
352 while (this_title != end_title) {
353 if ((this_title + 1) == end_title)
354 title += link + *this_title + "</a>";
355 else
356 title += *this_title + ": ";
357 this_title ++;
358 }
359
360 text_t creator;
361 bool first = true;
362 text_tarray::const_iterator this_creator = (*this_doc).metadata[1].values.begin();
363 text_tarray::const_iterator end_creator = (*this_doc).metadata[1].values.end();
364 while (this_creator != end_creator) {
365 if ((*this_creator).empty()) {this_creator ++; continue;}
366 if (first) creator += " by " + *this_creator;
367 else creator += " and " + *this_creator;
368 first = false;
369 this_creator ++;
370 }
371
372 textout << outconvert << disp << "<tr><td valign=top nowrap>" << link
373 << "_icontext_</a></td><td>" << title << creator << "</td></tr>\n";
374
375 this_doc ++;
376 }
377 textout << "</table>\n";
378
379 // output the footer
380 textout << outconvert << disp << "_query:footer_";
381 }
382 return true;
383}
384
385// define_query_macros sets the macros that couldn't be set until the
386// query had been done. Those macros are _freqmsg_, _quotedquery_,
387// _resultline_, _nextfirst_, _nextlast_, _prevfirst_, _prevlast_,
388// _thisfirst_, and _thislast_
389void queryaction::define_query_macros (cgiargsclass &args, displayclass &disp,
390 const FilterResponse_t &response,
391 const text_t &quotedstring) {
392
393 int numdocs = response.numDocs;
394 int arg_m = args.getintarg("m");
395 if (numdocs > arg_m)
396 numdocs = arg_m;
397
398 // set up _freqmsg_ and _quotedquery_ macros
399 text_t freqmsg = "_textfreqmsg1_";
400 TermInfo_tarray::const_iterator this_term = response.termInfo.begin();
401 TermInfo_tarray::const_iterator end_term = response.termInfo.end();
402 while (this_term != end_term) {
403 freqmsg += (*this_term).term + ": " + (*this_term).freq;
404 if ((this_term + 1) != end_term)
405 freqmsg += ", ";
406 this_term ++;
407 }
408
409 disp.setmacro ("quotedquery", "query", quotedstring);
410 disp.setmacro ("freqmsg", "query", freqmsg);
411
412
413 // set up _resultline_ macro
414 text_t resline;
415
416 // can't use isApprox here as it will be false as long
417 // as numDocs < MAXDOCS (currently 500). If arg_m is less
418 // than MAXDOCS numDocs can be greater than arg_m while
419 // isApprox is false.
420 if (response.numDocs > numdocs ||
421 ((response.numDocs == numdocs) && response.isApprox))
422 resline = "_textmorethan_";
423 if (numdocs == 0) resline = "_textnodocs_";
424 else if (numdocs == 1) resline += "_text1doc_";
425 else resline += text_t(numdocs) + " _textlotsdocs_";
426
427 disp.setmacro("resultline", "query", resline);
428
429
430 int firstdoc = args.getintarg("r");
431 int hitsperpage = args.getintarg("o");
432
433 // set up _thisfirst_ and _thislast_ macros
434 disp.setmacro ("thisfirst", "query", firstdoc);
435 int thislast = firstdoc + (hitsperpage - 1);
436 if (thislast > numdocs) thislast = numdocs;
437 disp.setmacro ("thislast", "query", thislast);
438
439 // set up _prevfirst_ and _prevlast_ macros
440 if (firstdoc > 1) {
441 disp.setmacro ("prevlast", "query", firstdoc - 1);
442 int prevfirst = firstdoc - hitsperpage;
443 if (prevfirst < 1) prevfirst = 1;
444 disp.setmacro ("prevfirst", "query", prevfirst);
445 }
446
447 // set up _nextfirst_ and _nextlast_ macros
448 if (thislast < numdocs) {
449 disp.setmacro ("nextfirst", "query", thislast + 1);
450 int nextlast = thislast + hitsperpage;
451 if (nextlast > numdocs) nextlast = numdocs;
452 disp.setmacro ("nextlast", "query", nextlast);
453 }
454}
455
456
457
Note: See TracBrowser for help on using the repository browser.