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

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

6th commit for security of cgiargs. Looked over all occurrences of setmacro in *action.cpp files

  • 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=" + encodeForURL(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.