source: main/trunk/greenstone2/runtime-src/src/recpt/dynamicclassifieraction.cpp@ 28899

Last change on this file since 28899 was 28899, checked in by ak19, 10 years ago

Third commit for security, for ensuring cgiargs macros are websafe. This time all the changes to the runtime action classes.

  • Property svn:executable set to *
File size: 27.4 KB
Line 
1/**********************************************************************
2 *
3 * dynamicclassifieraction.cpp --
4 * Copyright (C) 2008 DL Consulting Ltd
5 *
6 * By Michael Dewsnip
7 * Please do not edit this file without checking with Michael first!
8 *
9 * A component of the Greenstone digital library software
10 * from the New Zealand Digital Library Project at the
11 * University of Waikato, New Zealand.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 *********************************************************************/
28
29#include "dynamicclassifieraction.h"
30#include "recptprototools.h"
31
32
33dynamicclassifieraction::dynamicclassifieraction ()
34{
35 recpt = NULL;
36
37 cgiarginfo arg_ainfo;
38 arg_ainfo.shortname = "dcl";
39 arg_ainfo.longname = "dynamic classifier ID";
40 arg_ainfo.multiplechar = true;
41 arg_ainfo.multiplevalue = false;
42 arg_ainfo.defaultstatus = cgiarginfo::weak;
43 arg_ainfo.argdefault = "";
44 arg_ainfo.savedarginfo = cgiarginfo::must;
45 argsinfo.addarginfo (NULL, arg_ainfo);
46
47 arg_ainfo.shortname = "dcn";
48 arg_ainfo.longname = "dynamic classifier node";
49 arg_ainfo.multiplechar = true;
50 arg_ainfo.multiplevalue = false;
51 arg_ainfo.defaultstatus = cgiarginfo::weak;
52 arg_ainfo.argdefault = "";
53 arg_ainfo.savedarginfo = cgiarginfo::must;
54 argsinfo.addarginfo (NULL, arg_ainfo);
55}
56
57
58dynamicclassifieraction::~dynamicclassifieraction()
59{
60}
61
62
63bool dynamicclassifieraction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
64 recptprotolistclass *protos, ostream &logout)
65{
66 return true;
67}
68
69
70void dynamicclassifieraction::get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
71 response_t &response,text_t &response_data,
72 ostream &logout)
73{
74 response = content;
75 response_data = "text/html";
76}
77
78
79void dynamicclassifieraction::define_external_macros (displayclass &disp, cgiargsclass &args,
80 recptprotolistclass *protos, ostream &logout)
81{
82 // Some pages (e.g. the library home page) are not collection-specific
83 if (args["c"].empty())
84 {
85 return;
86 }
87
88 // A valid collection server is vital
89 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
90 if (collectproto == NULL)
91 {
92 logout << "dynamicclassifieraction::define_external_macros called with NULL collectproto\n";
93 return;
94 }
95
96 // Define _dynamicclassifiernavbarentries_ to add buttons to the navigation bar for the dynamic classifiers
97 text_t navigation_bar_entries = "";
98 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
99 text_tmap::iterator dynamic_classifier_iterator = cinfo->dynamic_classifiers.begin();
100 while (dynamic_classifier_iterator != cinfo->dynamic_classifiers.end())
101 {
102 text_t dynamic_classifier_id = (*dynamic_classifier_iterator).first;
103 navigation_bar_entries += "_navbarspacer_";
104 navigation_bar_entries += "_navtab_(_gwcgi_?c=" + args["c"] + "&amp;a=dc&amp;dcl=" + dynamic_classifier_id + "," + dynamic_classifier_id;
105 if (args["a"] == "dc" && args["dcl"] == dynamic_classifier_id)
106 {
107 navigation_bar_entries += ",selected";
108 }
109 navigation_bar_entries += ")";
110 dynamic_classifier_iterator++;
111 }
112
113 disp.setmacro("dynamicclassifiernavbarentries", displayclass::defaultpackage, navigation_bar_entries);
114}
115
116
117void dynamicclassifieraction::define_internal_macros (displayclass &disp, cgiargsclass &args,
118 recptprotolistclass *protos, ostream &logout)
119{
120 // No internal macros set
121}
122
123
124bool dynamicclassifieraction::do_action(cgiargsclass &args, recptprotolistclass *protos,
125 browsermapclass *browsers, displayclass &disp,
126 outconvertclass &outconvert, ostream &textout,
127 ostream &logout)
128{
129 // A valid collection server is vital
130 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
131 if (collectproto == NULL)
132 {
133 logout << "dynamicclassifieraction::do_action called with NULL collectproto\n";
134 return false;
135 }
136
137 textout << outconvert << disp << "_dynamicclassifier:header_\n";
138 textout << outconvert << disp << "_dynamicclassifier:content_\n";
139
140 // Check a dynamic classifier ID has been specified
141 text_t arg_dcl = args["dcl"];
142 if (arg_dcl.empty())
143 {
144 textout << outconvert << disp << "Error: Missing dcl argument.\n";
145 textout << outconvert << disp << "_dynamicclassifier:footer_\n";
146 return true;
147 }
148
149 // Check the dynamic classifier ID is valid (ie. there is an entry in the collect.cfg file for it)
150 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
151 if (cinfo->dynamic_classifiers.find(arg_dcl) == cinfo->dynamic_classifiers.end())
152 {
153 textout << outconvert << disp << "Error: Invalid dcl value \"" << encodeForHTML(arg_dcl) << "\".\n";
154 textout << outconvert << disp << "_dynamicclassifier:footer_\n";
155 return true;
156 }
157
158 // Parse the classifier options from the specification
159 text_t classifier_specification = cinfo->dynamic_classifiers[arg_dcl];
160 text_tmap classifier_options = parse_classifier_options (classifier_specification, args);
161
162 // Output the "<ID>Header" format statement if there is one
163 text_t classifier_header_format_statement = "";
164 get_formatstring (arg_dcl + "Header", cinfo->format, classifier_header_format_statement);
165 textout << outconvert << disp << classifier_header_format_statement << "\n";
166
167 // Resolve any ".pr" bits at the end of the "dcn" argument
168 text_t classifier_node_separator = classifier_options["-split_using_hierarchy_separator"];
169 if (ends_with (args["dcn"], ".pr"))
170 {
171 // Change the "dcn" argument to be the OID of the parent of the specified classifier node
172 text_tlist args_dcn_parts;
173 splitword (args["dcn"].begin(), args["dcn"].end(), classifier_node_separator, args_dcn_parts);
174 args_dcn_parts.pop_back(); // Remove the last part
175 joinchar (args_dcn_parts, classifier_node_separator, args["dcn"]);
176 }
177
178 // Prepare to output the dynamic classifier
179 text_t current_classifier_node_OID = "";
180 text_t current_metadata_value_filter = "";
181 int classifier_node_indent = 0;
182
183 // (Optional) Output an hlist to group the classifier nodes into buckets based on the first character
184 if (classifier_options["-group_by_first_character"] == "1")
185 {
186 text_t selected_grouping_node_OID = output_hlist_classifier_nodes (current_classifier_node_OID, current_metadata_value_filter, "substr(value,1,1)", classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
187
188 current_classifier_node_OID = selected_grouping_node_OID + ".";
189 current_metadata_value_filter = selected_grouping_node_OID + "*";
190 }
191
192 // (Optional) Output an hlist instead of a vlist at the top level
193 if (classifier_options["-use_hlist_at_top"] == "1")
194 {
195 text_t selected_hlist_node_OID = output_hlist_classifier_nodes (current_classifier_node_OID, current_metadata_value_filter, "", classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
196
197 current_classifier_node_OID = selected_hlist_node_OID + classifier_node_separator;
198 }
199
200 // args["dcn"] may have been modified by output_hlist_classifier_nodes() above
201 text_t classifier_node_OID = args["dcn"];
202
203 // If grouping is enabled remove the grouping node bit from the start of the OID
204 text_t classifier_node_OID_sans_grouping = classifier_node_OID;
205 if (classifier_options["-group_by_first_character"] == "1")
206 {
207 text_t::iterator grouping_node_separator = findchar (classifier_node_OID.begin(), classifier_node_OID.end(), '.');
208 if (grouping_node_separator != classifier_node_OID.end())
209 {
210 classifier_node_OID_sans_grouping = substr (grouping_node_separator + 1, classifier_node_OID.end());
211 }
212 else
213 {
214 classifier_node_OID_sans_grouping = "";
215 }
216 }
217
218 // Split the classifier node OID into its hierarchical parts, then remove any we've already dealt with (HLists)
219 text_tlist classifier_node_OID_parts_remaining;
220 splitword (classifier_node_OID_sans_grouping.begin(), classifier_node_OID_sans_grouping.end(), classifier_node_separator, classifier_node_OID_parts_remaining);
221 if (classifier_options["-use_hlist_at_top"] == "1")
222 {
223 classifier_node_OID_parts_remaining.pop_front();
224 }
225
226 text_t classifier_node_metadata_value = classifier_node_OID_sans_grouping;
227 text_t classifier_node_metadata_value_filter = classifier_node_metadata_value + classifier_node_separator + "*";
228
229 // If "-split_greenstone_dates" is on the metadata value and filter doesn't quite match the OID -- fix this
230 if (classifier_options["-split_greenstone_dates"] == "1")
231 {
232 classifier_node_metadata_value.replace (classifier_node_separator, "");
233 classifier_node_metadata_value_filter = classifier_node_metadata_value;
234 if (classifier_node_metadata_value_filter.size() == 8)
235 {
236 classifier_node_metadata_value_filter += classifier_node_separator;
237 }
238 classifier_node_metadata_value_filter += "*";
239 }
240
241 // Simple case at the top level: just output the child classifier nodes
242 if (classifier_node_metadata_value == "")
243 {
244 output_child_classifier_nodes (current_classifier_node_OID, "", current_metadata_value_filter, classifier_node_indent, classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
245 }
246
247 // More complex case below the top level
248 else
249 {
250 // Output the parent classifier nodes and the current classifier node
251 output_upper_classifier_nodes (current_classifier_node_OID, classifier_node_OID_parts_remaining, classifier_node_indent, classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
252
253 // Output the child classifier nodes
254 current_classifier_node_OID = classifier_node_OID + classifier_node_separator;
255 output_child_classifier_nodes (current_classifier_node_OID, classifier_node_metadata_value, classifier_node_metadata_value_filter, classifier_node_indent, classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
256
257 // Get the document nodes at this level
258 text_t metadata_elements = classifier_options["metadata_elements"];
259 text_t sort_documents_by = classifier_options["-sort_documents_by"];
260 FilterResponse_t documents_response;
261 get_documents_with_metadata_value (metadata_elements, classifier_node_metadata_value, sort_documents_by, args["c"], collectproto, documents_response, logout);
262
263 // Display the document nodes
264 display_document_nodes (documents_response, classifier_node_indent, args, collectproto, browsers, disp, outconvert, textout, logout);
265 }
266
267 // Output the "<ID>Footer" format statement if there is one
268 text_t classifier_footer_format_statement = "";
269 get_formatstring (arg_dcl + "Footer", cinfo->format, classifier_footer_format_statement);
270 textout << outconvert << disp << classifier_footer_format_statement << "\n";
271
272 textout << outconvert << disp << "_dynamicclassifier:footer_\n";
273 return true;
274}
275
276
277text_tmap dynamicclassifieraction::parse_classifier_options (text_t classifier_specification, cgiargsclass &args)
278{
279 text_tmap classifier_options;
280
281 // Default values
282 classifier_options["-split_using_hierarchy_separator"] = "|";
283
284 // Split the classifier specification string by spaces
285 text_tlist classifier_specification_parts;
286 splitchar (classifier_specification.begin(), classifier_specification.end(), ' ', classifier_specification_parts);
287
288 // The metadata element(s) to classify by should be the first value
289 classifier_options["metadata_elements"] = classifier_specification_parts.front();
290 classifier_specification_parts.pop_front();
291
292 // Parse options from the remainder of the classifier specification
293 while (!classifier_specification_parts.empty())
294 {
295 // Parse the option name
296 text_t classifier_option_name = classifier_specification_parts.front();
297 classifier_specification_parts.pop_front();
298
299 // Check if the option has a value (it may just be a flag, in which case we use "1" as the value)
300 text_t classifier_option_value = "1";
301 if (!classifier_specification_parts.empty() && !starts_with(classifier_specification_parts.front(), "-"))
302 {
303 classifier_option_value = classifier_specification_parts.front();
304 classifier_specification_parts.pop_front();
305 }
306
307 // Record the option
308 classifier_options[classifier_option_name] = classifier_option_value;
309 }
310
311 return classifier_options;
312}
313
314
315text_t dynamicclassifieraction::output_hlist_classifier_nodes (text_t parent_classifier_node_OID,
316 text_t metadata_value_filter,
317 text_t metadata_value_grouping_expression,
318 text_tmap classifier_options, cgiargsclass &args,
319 recptproto *collectproto, browsermapclass *browsers,
320 displayclass &disp, outconvertclass &outconvert,
321 ostream &textout, ostream &logout)
322{
323 // Get all the metadata values for the specified element(s) that match the filter
324 text_t metadata_elements = classifier_options["metadata_elements"];
325 FilterResponse_t metadata_values_response;
326 bool request_success = get_metadata_values (metadata_elements, metadata_value_filter, metadata_value_grouping_expression, args["c"], collectproto, metadata_values_response, logout);
327
328 // If the request failed then it's probably because the collection isn't using an SQL infodbtype
329 if (request_success == false)
330 {
331 textout << outconvert << disp << "Error: Dynamic classifier functionality is not available. Please check you are using an SQL infodbtype and the collection has been rebuilt.\n";
332 return "";
333 }
334
335 // Check some metadata values were returned
336 if (metadata_values_response.docInfo.empty())
337 {
338 return "";
339 }
340
341 // After processing any hierarchical metadata values we're left with the hlist classifer nodes
342 map<text_t, int, lttext_t> hlist_classifier_nodes;
343 ResultDocInfo_tarray::iterator metadata_value_iterator = metadata_values_response.docInfo.begin();
344 while (metadata_value_iterator != metadata_values_response.docInfo.end())
345 {
346 text_t hierarchical_metadata_value = split_metadata_value ((*metadata_value_iterator).OID, classifier_options);
347
348 // Assume for now we're always at the top
349 text_t hlist_metadata_value = hierarchical_metadata_value;
350
351 // Determine the label for the hlist classifier node from the metadata value
352 text_tlist hlist_metadata_value_parts;
353 text_t hlist_node_separator = classifier_options["-split_using_hierarchy_separator"];
354 splitword (hlist_metadata_value.begin(), hlist_metadata_value.end(), hlist_node_separator, hlist_metadata_value_parts);
355 text_t hlist_classifier_node_label = hlist_metadata_value_parts.front();
356
357 // Create a node for this value if we haven't seen it before
358 if (hlist_classifier_nodes.find(hlist_classifier_node_label) == hlist_classifier_nodes.end())
359 {
360 hlist_classifier_nodes[hlist_classifier_node_label] = 0;
361 }
362
363 // Increment the occurrence count
364 hlist_classifier_nodes[hlist_classifier_node_label] += (*metadata_value_iterator).result_num;
365
366 metadata_value_iterator++;
367 }
368
369 // Add the necessary metadata to the hlist classifier nodes
370 text_t selected_hlist_node_OID = "";
371 FilterResponse_t hlist_classifier_nodes_response;
372 map<text_t, int, lttext_t>::iterator hlist_classifier_nodes_iterator = hlist_classifier_nodes.begin();
373 while (hlist_classifier_nodes_iterator != hlist_classifier_nodes.end())
374 {
375 text_t hlist_classifier_node_OID = parent_classifier_node_OID + (*hlist_classifier_nodes_iterator).first;
376
377 // Is this the hlist node that is currently selected?
378 if (starts_with (args["dcn"], hlist_classifier_node_OID))
379 {
380 selected_hlist_node_OID = hlist_classifier_node_OID;
381 }
382
383 // Add the necessary metadata required to display the hlist nodes correctly
384 ResultDocInfo_t hlist_classifier_node;
385 hlist_classifier_node.OID = hlist_classifier_node_OID;
386 hlist_classifier_node.metadata["doctype"].values.push_back ("classify");
387 hlist_classifier_node.metadata["haschildren"].values.push_back ("1");
388 hlist_classifier_node.metadata["numleafdocs"].values.push_back ("?"); // We can't determine this without more database requests
389 hlist_classifier_node.metadata["Title"].values.push_back ((*hlist_classifier_nodes_iterator).first);
390 hlist_classifier_nodes_response.docInfo.push_back (hlist_classifier_node);
391
392 hlist_classifier_nodes_iterator++;
393 }
394
395 // Automatically select the first hlist node if necessary
396 if (selected_hlist_node_OID == "")
397 {
398 selected_hlist_node_OID = (*hlist_classifier_nodes_response.docInfo.begin()).OID;
399
400 // Don't really like messing with this here, but it needs to be done before display_classifier_nodes() below
401 if (starts_with (parent_classifier_node_OID, args["dcn"]))
402 {
403 args["dcn"] = selected_hlist_node_OID;
404 }
405 }
406
407 // Display the hlist nodes
408 display_classifier_nodes (hlist_classifier_nodes_response, "HList", 0, args, collectproto, browsers, disp, outconvert, textout, logout);
409
410 return selected_hlist_node_OID;
411}
412
413
414void dynamicclassifieraction::output_upper_classifier_nodes (text_t root_classifier_node_OID,
415 text_tlist upper_classifier_node_labels,
416 int& classifier_node_indent,
417 text_tmap classifier_options, cgiargsclass &args,
418 recptproto *collectproto, browsermapclass *browsers,
419 displayclass &disp, outconvertclass &outconvert,
420 ostream &textout, ostream &logout)
421{
422 // Display the upper classifier nodes
423 text_t upper_classifier_node_OID = root_classifier_node_OID;
424 text_tlist::iterator upper_classifier_node_labels_iterator = upper_classifier_node_labels.begin();
425 while (upper_classifier_node_labels_iterator != upper_classifier_node_labels.end())
426 {
427 upper_classifier_node_OID += *upper_classifier_node_labels_iterator;
428
429 ResultDocInfo_t upper_classifier_node;
430 upper_classifier_node.OID = upper_classifier_node_OID;
431 upper_classifier_node.metadata["doctype"].values.push_back ("classify");
432 upper_classifier_node.metadata["haschildren"].values.push_back ("1");
433 upper_classifier_node.metadata["numleafdocs"].values.push_back ("?"); // We can't determine this without more database requests
434 upper_classifier_node.metadata["Title"].values.push_back (*upper_classifier_node_labels_iterator);
435
436 FilterResponse_t upper_classifier_node_response;
437 upper_classifier_node_response.docInfo.push_back(upper_classifier_node);
438 display_classifier_nodes (upper_classifier_node_response, "VList", classifier_node_indent, args, collectproto, browsers, disp, outconvert, textout, logout);
439 classifier_node_indent++;
440
441 upper_classifier_node_OID += classifier_options["-split_using_hierarchy_separator"];
442 upper_classifier_node_labels_iterator++;
443 }
444}
445
446
447void dynamicclassifieraction::output_child_classifier_nodes (text_t classifier_node_OID,
448 text_t classifier_node_metadata_value,
449 text_t metadata_value_filter,
450 int& classifier_node_indent,
451 text_tmap classifier_options, cgiargsclass &args,
452 recptproto *collectproto, browsermapclass *browsers,
453 displayclass &disp, outconvertclass &outconvert,
454 ostream &textout, ostream &logout)
455{
456 // Get all the metadata values for the specified element(s) that match the filter
457 text_t metadata_elements = classifier_options["metadata_elements"];
458 FilterResponse_t metadata_values_response;
459 bool request_success = get_metadata_values (metadata_elements, metadata_value_filter, "", args["c"], collectproto, metadata_values_response, logout);
460
461 // If the request failed then it's probably because the collection isn't using an SQL infodbtype
462 if (request_success == false)
463 {
464 textout << outconvert << disp << "Error: Dynamic classifier functionality is not available. Please check you are using an SQL infodbtype and the collection has been rebuilt.\n";
465 return;
466 }
467
468 // After processing any hierarchical metadata values we're left with the child classifer nodes
469 map<text_t, int, lttext_t> child_classifier_nodes;
470 ResultDocInfo_tarray::iterator metadata_value_iterator = metadata_values_response.docInfo.begin();
471 while (metadata_value_iterator != metadata_values_response.docInfo.end())
472 {
473 text_t hierarchical_metadata_value = split_metadata_value ((*metadata_value_iterator).OID, classifier_options);
474 text_t classifier_node_hierarchical_metadata_value = split_metadata_value (classifier_node_metadata_value, classifier_options);
475
476 // We need to remove the current position from the metadata value to leave the child metadata value
477 text_t child_metadata_value = hierarchical_metadata_value;
478 text_t child_node_separator = classifier_options["-split_using_hierarchy_separator"];
479 if (starts_with(hierarchical_metadata_value, classifier_node_hierarchical_metadata_value + child_node_separator))
480 {
481 child_metadata_value = substr(hierarchical_metadata_value.begin() + (classifier_node_hierarchical_metadata_value + child_node_separator).size(), hierarchical_metadata_value.end());
482 }
483
484 // Determine the label for the child classifier node from the metadata value
485 text_tlist child_metadata_value_parts;
486 splitword (child_metadata_value.begin(), child_metadata_value.end(), child_node_separator, child_metadata_value_parts);
487 text_t child_classifier_node_label = child_metadata_value_parts.front();
488
489 // Create a node for this value if we haven't seen it before
490 if (child_classifier_nodes.find(child_classifier_node_label) == child_classifier_nodes.end())
491 {
492 child_classifier_nodes[child_classifier_node_label] = 0;
493 }
494
495 // Increment the occurrence count
496 child_classifier_nodes[child_classifier_node_label] += (*metadata_value_iterator).result_num;
497
498 metadata_value_iterator++;
499 }
500
501 // Add the necessary metadata to the child classifier nodes
502 FilterResponse_t child_classifier_nodes_response;
503 map<text_t, int, lttext_t>::iterator child_classifier_nodes_iterator = child_classifier_nodes.begin();
504 while (child_classifier_nodes_iterator != child_classifier_nodes.end())
505 {
506 text_t child_classifier_node_OID = classifier_node_OID + (*child_classifier_nodes_iterator).first;
507
508 ResultDocInfo_t child_classifier_node;
509 child_classifier_node.OID = child_classifier_node_OID;
510 child_classifier_node.metadata["doctype"].values.push_back ("classify");
511 child_classifier_node.metadata["haschildren"].values.push_back ("1");
512 child_classifier_node.metadata["numleafdocs"].values.push_back ((*child_classifier_nodes_iterator).second);
513 child_classifier_node.metadata["Title"].values.push_back ((*child_classifier_nodes_iterator).first);
514 child_classifier_nodes_response.docInfo.push_back (child_classifier_node);
515
516 child_classifier_nodes_iterator++;
517 }
518
519 // Display the child classifier nodes
520 display_classifier_nodes (child_classifier_nodes_response, "VList", classifier_node_indent, args, collectproto, browsers, disp, outconvert, textout, logout);
521}
522
523
524text_t dynamicclassifieraction::split_metadata_value (text_t metadata_value, text_tmap classifier_options)
525{
526 text_t hierarchical_metadata_value = metadata_value;
527 text_t hierarchy_separator = classifier_options["-split_using_hierarchy_separator"];
528
529 // Add hierarchy separators into Greenstone date values (e.g. YYYYMMDD -> YYYY|MM|DD)
530 if (classifier_options["-split_greenstone_dates"] == "1")
531 {
532 if (metadata_value.size() == 4 || metadata_value.size() == 6 || metadata_value.size() == 8)
533 {
534 // Add year
535 hierarchical_metadata_value = substr (metadata_value.begin(), metadata_value.begin() + 4);
536 if (metadata_value.size() == 6 || metadata_value.size() == 8)
537 {
538 // Add month
539 hierarchical_metadata_value += hierarchy_separator;
540 hierarchical_metadata_value += substr (metadata_value.begin() + 4, metadata_value.begin() + 6);
541 if (metadata_value.size() == 8)
542 {
543 // Add day
544 hierarchical_metadata_value += hierarchy_separator;
545 hierarchical_metadata_value += substr (metadata_value.begin() + 6, metadata_value.begin() + 8);
546 }
547 }
548 }
549 }
550
551 return hierarchical_metadata_value;
552}
553
554
555void dynamicclassifieraction::display_classifier_nodes (FilterResponse_t classifier_nodes_response,
556 text_t classifier_nodes_type,
557 int classifier_nodes_indent,
558 cgiargsclass &args, recptproto *collectproto,
559 browsermapclass *browsers, displayclass &disp,
560 outconvertclass &outconvert, ostream &textout,
561 ostream &logout)
562{
563 // Check there are some classifier nodes to display
564 if (classifier_nodes_response.docInfo.empty()) return;
565
566 // Get the format statement for this classifier if there is one, or use the browser's default otherwise
567 text_t formatstring;
568 browserclass *bptr = browsers->getbrowser (classifier_nodes_type);
569 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
570 if (!get_formatstring (args["dcl"], classifier_nodes_type, cinfo->format, formatstring))
571 {
572 formatstring = bptr->get_default_formatstring();
573 }
574 format_t *formatlistptr = new format_t();
575 text_tset metadata;
576 bool getParents = false;
577 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
578 bool use_table = is_table_content (formatlistptr);
579
580 // Display the classifier nodes
581 bptr->output_section_group (classifier_nodes_response, args, args["c"], classifier_nodes_indent, formatlistptr, use_table, metadata, getParents, collectproto, disp, outconvert, textout, logout);
582}
583
584
585void dynamicclassifieraction::display_document_nodes (FilterResponse_t documents_response,
586 int document_nodes_indent,
587 cgiargsclass &args, recptproto *collectproto,
588 browsermapclass *browsers, displayclass &disp,
589 outconvertclass &outconvert, ostream &textout,
590 ostream &logout)
591{
592 // Check there are some documents to display
593 if (documents_response.docInfo.empty()) return;
594
595 // Get the format statement for the document nodes if there is one, or use the browser's default otherwise
596 text_t formatstring;
597 browserclass *bptr = browsers->getbrowser ("VList");
598 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
599 if (!get_formatstring (args["dcl"], "DocumentNodes", cinfo->format, formatstring))
600 {
601 if (!get_formatstring (args["dcl"], "VList", cinfo->format, formatstring))
602 {
603 formatstring = bptr->get_default_formatstring();
604 }
605 }
606 format_t *formatlistptr = new format_t();
607 text_tset metadata;
608 bool getParents = false;
609 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
610 bool use_table = is_table_content (formatlistptr);
611
612 // Request the necessary metadata for displaying the documents
613 text_tarray document_OIDs;
614 ResultDocInfo_tarray::iterator document_iterator = documents_response.docInfo.begin();
615 while (document_iterator != documents_response.docInfo.end())
616 {
617 document_OIDs.push_back ((*document_iterator).OID);
618 document_iterator++;
619 }
620 FilterResponse_t document_nodes_response;
621 get_info (document_OIDs, args["c"], args["l"], metadata, getParents, collectproto, document_nodes_response, logout);
622
623 // Display the document nodes
624 bptr->output_section_group (document_nodes_response, args, args["c"], document_nodes_indent, formatlistptr, use_table, metadata, getParents, collectproto, disp, outconvert, textout, logout);
625}
Note: See TracBrowser for help on using the repository browser.