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

Last change on this file since 295 was 295, checked in by rjmcnab, 25 years ago

Made h, i, and n arguments saved in the compressed arguments.

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