source: gsdl/trunk/src/recpt/dynamicclassifieraction.cpp@ 16114

Last change on this file since 16114 was 16114, checked in by mdewsnip, 16 years ago

Adding initial support for a "-use_hlist_at_top" option. Code tidying up to come.

  • Property svn:executable set to *
File size: 27.5 KB
RevLine 
[15744]1/**********************************************************************
2 *
3 * dynamicclassifieraction.cpp --
4 * Copyright (C) 2008 DL Consulting Ltd
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 "dynamicclassifieraction.h"
[15768]27#include "recptprototools.h"
[15744]28
29
30dynamicclassifieraction::dynamicclassifieraction ()
31{
32 recpt = NULL;
[15772]33
34 cgiarginfo arg_ainfo;
[15795]35 arg_ainfo.shortname = "dcl";
36 arg_ainfo.longname = "dynamic classifier ID";
[15772]37 arg_ainfo.multiplechar = true;
38 arg_ainfo.defaultstatus = cgiarginfo::weak;
39 arg_ainfo.argdefault = "";
40 arg_ainfo.savedarginfo = cgiarginfo::must;
41 argsinfo.addarginfo (NULL, arg_ainfo);
[15807]42
43 arg_ainfo.shortname = "dcn";
44 arg_ainfo.longname = "dynamic classifier node";
45 arg_ainfo.multiplechar = true;
46 arg_ainfo.defaultstatus = cgiarginfo::weak;
47 arg_ainfo.argdefault = "";
48 arg_ainfo.savedarginfo = cgiarginfo::must;
49 argsinfo.addarginfo (NULL, arg_ainfo);
[15744]50}
51
52
53dynamicclassifieraction::~dynamicclassifieraction()
54{
55}
56
57
58bool dynamicclassifieraction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
59 recptprotolistclass *protos, ostream &logout)
60{
61 return true;
62}
63
64
65void dynamicclassifieraction::get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
66 response_t &response,text_t &response_data,
67 ostream &logout)
68{
69 response = content;
70 response_data = "text/html";
71}
72
73
[15847]74// define all the macros which might be used by other actions to produce pages.
[15744]75void dynamicclassifieraction::define_external_macros (displayclass &disp, cgiargsclass &args,
76 recptprotolistclass *protos, ostream &logout)
77{
[15847]78 // A valid collection server is vital
79 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
80 if (collectproto == NULL)
81 {
82 logout << "dynamicclassifieraction::define_external_macros called with NULL collectproto\n";
83 return;
84 }
85
86 // Define _dynamicclassifiernavbarentries_ to add buttons to the navigation bar for the dynamic classifiers
87 text_t navigation_bar_entries = "";
88 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
89 text_tmap::iterator dynamic_classifier_iterator = cinfo->dynamic_classifiers.begin();
90 while (dynamic_classifier_iterator != cinfo->dynamic_classifiers.end())
91 {
92 text_t dynamic_classifier_id = (*dynamic_classifier_iterator).first;
93 navigation_bar_entries += "_navbarspacer_";
94 navigation_bar_entries += "_navtab_(_gwcgi_?c=" + args["c"] + "&amp;a=dc&amp;dcl=" + dynamic_classifier_id + "," + dynamic_classifier_id;
95 if (args["a"] == "dc" && args["dcl"] == dynamic_classifier_id)
96 {
97 navigation_bar_entries += ",selected";
98 }
99 navigation_bar_entries += ")";
100 dynamic_classifier_iterator++;
101 }
102
103 disp.setmacro("dynamicclassifiernavbarentries", displayclass::defaultpackage, navigation_bar_entries);
[15744]104}
105
106
107// define all the macros which are related to pages generated
108// by this action. we also load up the formatinfo structure
109// here (it's used in do_action as well as here)
110void dynamicclassifieraction::define_internal_macros (displayclass &disp, cgiargsclass &args,
111 recptprotolistclass *protos, ostream &logout)
112{
113 // define_internal_macros sets the following macros:
114}
115
116
117bool dynamicclassifieraction::do_action(cgiargsclass &args, recptprotolistclass *protos,
118 browsermapclass *browsers, displayclass &disp,
119 outconvertclass &outconvert, ostream &textout,
120 ostream &logout)
121{
[15795]122 // A valid collection server is vital
[15744]123 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
124 if (collectproto == NULL)
125 {
126 logout << "dynamicclassifieraction::do_action called with NULL collectproto\n";
127 return false;
128 }
129
[15988]130 textout << outconvert << disp << "_dynamicclassifier:header_\n";
131 textout << outconvert << disp << "_dynamicclassifier:content_\n";
[15768]132
[15795]133 // Check a dynamic classifier ID has been specified
134 text_t arg_dcl = args["dcl"];
135 if (arg_dcl.empty())
[15772]136 {
[15834]137 textout << outconvert << disp << "Error: Missing dcl argument.\n";
[15988]138 textout << outconvert << disp << "_dynamicclassifier:footer_\n";
[15795]139 return true;
[15772]140 }
141
[15795]142 // Check the dynamic classifier ID is valid (ie. there is an entry in the collect.cfg file for it)
[15772]143 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
[15795]144 if (cinfo->dynamic_classifiers.find(arg_dcl) == cinfo->dynamic_classifiers.end())
[15772]145 {
[15834]146 textout << outconvert << disp << "Error: Invalid dcl value \"" << arg_dcl << "\".\n";
[15988]147 textout << outconvert << disp << "_dynamicclassifier:footer_\n";
[15795]148 return true;
[15772]149 }
150
[15999]151 // Parse the classifier options from the specification
152 text_t classifier_specification = cinfo->dynamic_classifiers[arg_dcl];
[16032]153 text_tmap classifier_options = parse_classifier_options (classifier_specification, args);
[15999]154
[15993]155 // Output the "<ID>Header" format statement if there is one
156 text_t classifier_header_format_statement = "";
[15999]157 get_formatstring (arg_dcl + "Header", cinfo->format, classifier_header_format_statement);
[15993]158 textout << outconvert << disp << classifier_header_format_statement << "\n";
159
[16065]160 // Resolve any ".pr" bits at the end of the "dcn" argument
161 if (ends_with (args["dcn"], ".pr"))
162 {
163 // Change the "dcn" argument to be the OID of the parent of the specified classifier node
164 text_t::iterator parent_classifier_node_OID_end = findlastchar (args["dcn"].begin(), args["dcn"].end(), '|');
165 if (parent_classifier_node_OID_end != args["dcn"].end())
166 {
167 args["dcn"] = substr (args["dcn"].begin(), parent_classifier_node_OID_end);
168 }
169 else
170 {
171 args["dcn"] = "";
172 }
173 }
174
[16114]175 // Prepare to output the dynamic classifier
176 text_t classifier_node_OID = args["dcn"];
177 int classifier_node_indent = 0;
178
179 // Begin with the (optional) grouping nodes
[16046]180 text_t selected_grouping_node_OID = "";
181 if (!classifier_options["-group_using"].empty())
[15795]182 {
[16046]183 selected_grouping_node_OID = output_grouping_nodes (classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
[16114]184 classifier_node_OID = args["dcn"]; // args["dcn"] may have been modified by output_grouping_nodes()
[16046]185 }
[16057]186
[16114]187 // Next, optionally display an hlist level
188 text_t selected_hlist_node_OID = "";
189 if (classifier_options["-use_hlist_at_top"] == "1")
190 {
191 text_t parent_classifier_node_OID = selected_grouping_node_OID;
192 text_t classifier_node_metadata_value = selected_grouping_node_OID;
193 text_t metadata_value_filter = selected_grouping_node_OID + "*";
194 selected_hlist_node_OID = output_hlist_classifier_nodes (parent_classifier_node_OID, classifier_node_metadata_value, metadata_value_filter, classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
195 classifier_node_OID = args["dcn"]; // args["dcn"] may have been modified by output_hlist_classifier_nodes()
196 }
197
[16057]198 // Simple case at the top level: just output the child classifier nodes
[16061]199 if (classifier_node_OID == selected_grouping_node_OID)
[16046]200 {
[16061]201 text_t metadata_value_filter = selected_grouping_node_OID + "*";
202 output_child_classifier_nodes (classifier_node_OID, "", metadata_value_filter, classifier_node_indent, classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
[15795]203 }
[16057]204
205 // More complex case below the top level
[15949]206 else
207 {
[16061]208 // This is the classifier node OID without any grouping information
209 text_t classifier_node_OID_sans_grouping = classifier_node_OID;
210 if (starts_with (classifier_node_OID, selected_grouping_node_OID + "|"))
211 {
212 classifier_node_OID_sans_grouping = substr (classifier_node_OID.begin() + (selected_grouping_node_OID + "|").size(), classifier_node_OID.end());
213 }
[16057]214
[16114]215 // This is the classifier node OID without any hlist nodes
216 text_t classifier_node_OID_sans_hlists = classifier_node_OID;
217 if (classifier_node_OID == selected_hlist_node_OID)
218 {
219 classifier_node_OID_sans_hlists = "";
220 }
221 else if (starts_with (classifier_node_OID, selected_hlist_node_OID + "|"))
222 {
223 classifier_node_OID_sans_hlists = substr (classifier_node_OID.begin() + (selected_hlist_node_OID + "|").size(), classifier_node_OID.end());
224 }
225
[16061]226 // Determine the parent classifier node labels
227 text_tlist parent_classifier_node_labels;
[16114]228 splitchar(classifier_node_OID_sans_hlists.begin(), classifier_node_OID_sans_hlists.end(), '|', parent_classifier_node_labels);
[16057]229
[16061]230 // Output the parent classifier nodes and the current classifier node
[16114]231 output_upper_classifier_nodes (selected_hlist_node_OID, parent_classifier_node_labels, classifier_node_indent, classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
[16061]232
[16057]233 // Output the child classifier nodes
[16061]234 text_t classifier_node_metadata_value = classifier_node_OID_sans_grouping;
235 text_t metadata_value_filter = classifier_node_OID_sans_grouping + "|*";
236 output_child_classifier_nodes (classifier_node_OID, classifier_node_metadata_value, metadata_value_filter, classifier_node_indent, classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
[16057]237
238 // Get the document nodes at this level
239 text_t metadata_element_name = classifier_options["metadata_element_name"];
240 text_t sort_documents_by = classifier_options["-sort_documents_by"];
241 FilterResponse_t documents_response;
242 get_documents_with_metadata_value (metadata_element_name, classifier_node_metadata_value, sort_documents_by, args["c"], collectproto, documents_response, logout);
243
244 // Display the document nodes
245 display_document_nodes (documents_response, classifier_node_indent, args, collectproto, browsers, disp, outconvert, textout, logout);
[15949]246 }
[15795]247
[15993]248 // Output the "<ID>Footer" format statement if there is one
249 text_t classifier_footer_format_statement = "";
[15999]250 get_formatstring (arg_dcl + "Footer", cinfo->format, classifier_footer_format_statement);
[15993]251 textout << outconvert << disp << classifier_footer_format_statement << "\n";
252
[15988]253 textout << outconvert << disp << "_dynamicclassifier:footer_\n";
[15949]254 return true;
255}
256
257
[16032]258text_tmap dynamicclassifieraction::parse_classifier_options (text_t classifier_specification, cgiargsclass &args)
259{
260 text_tmap classifier_options;
261
[16033]262 // Split the classifier specification string by spaces
263 text_tlist classifier_specification_parts;
264 splitchar (classifier_specification.begin(), classifier_specification.end(), ' ', classifier_specification_parts);
265
266 // The metadata element to classify by should be the first value
267 classifier_options["metadata_element_name"] = classifier_specification_parts.front();
268 classifier_specification_parts.pop_front();
269
270 // Parse options from the remainder of the classifier specification
271 while (!classifier_specification_parts.empty())
272 {
273 // Parse the option name
274 text_t classifier_option_name = classifier_specification_parts.front();
275 classifier_specification_parts.pop_front();
276
277 // Check if the option has a value (it may just be a flag, in which case we use "1" as the value)
278 text_t classifier_option_value = "1";
279 if (!classifier_specification_parts.empty() && !starts_with(classifier_specification_parts.front(), "-"))
280 {
281 classifier_option_value = classifier_specification_parts.front();
282 classifier_specification_parts.pop_front();
283 }
284
285 // Record the option
286 classifier_options[classifier_option_name] = classifier_option_value;
287 }
288
[16032]289 return classifier_options;
290}
291
292
[16046]293text_t dynamicclassifieraction::output_grouping_nodes (text_tmap classifier_options, cgiargsclass &args,
294 recptproto *collectproto, browsermapclass *browsers,
295 displayclass &disp, outconvertclass &outconvert,
296 ostream &textout, ostream &logout)
297{
298 // Get all the metadata values for the specified element, and group them according to the "-group_using" value
299 text_t metadata_element_name = classifier_options["metadata_element_name"];
300 text_t metadata_value_grouping_expression = classifier_options["-group_using"];
301 FilterResponse_t grouping_nodes_response;
302 bool request_success = get_metadata_values (metadata_element_name, "", metadata_value_grouping_expression, args["c"], collectproto, grouping_nodes_response, logout);
303
304 // If the request failed then it's probably because the collection isn't using an SQL infodbtype
305 if (request_success == false)
306 {
307 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";
308 return "";
309 }
310
311 // Check some grouping nodes were returned
312 if (grouping_nodes_response.docInfo.empty())
313 {
314 return "";
315 }
316
317 // If no classifier node has been specified automatically go to the first grouping node
318 if (args["dcn"] == "")
319 {
320 args["dcn"] = grouping_nodes_response.docInfo.front().OID;
321 }
322
[16112]323 // Add the necessary metadata to the grouping nodes
[16046]324 text_t selected_grouping_node_OID = "";
325 ResultDocInfo_tarray::iterator grouping_node_iterator = grouping_nodes_response.docInfo.begin();
326 while (grouping_node_iterator != grouping_nodes_response.docInfo.end())
327 {
328 // Is this the grouping node that is currently selected?
[16061]329 if (starts_with (args["dcn"], (*grouping_node_iterator).OID))
[16046]330 {
331 selected_grouping_node_OID = (*grouping_node_iterator).OID;
332 }
333
334 // Add the necessary metadata required to display the grouping nodes correctly
335 (*grouping_node_iterator).metadata["doctype"].values.push_back ("classify");
336 (*grouping_node_iterator).metadata["haschildren"].values.push_back ("1");
337 (*grouping_node_iterator).metadata["numleafdocs"].values.push_back ("?"); // We can't determine this without more database requests
338 (*grouping_node_iterator).metadata["Title"].values.push_back ((*grouping_node_iterator).OID);
339 grouping_node_iterator++;
340 }
341
342 // Display the grouping nodes
[16112]343 display_classifier_nodes (grouping_nodes_response, "HList", 0, args, collectproto, browsers, disp, outconvert, textout, logout);
[16046]344
345 return selected_grouping_node_OID;
346}
347
348
[16114]349text_t dynamicclassifieraction::output_hlist_classifier_nodes (text_t parent_classifier_node_OID,
350 text_t classifier_node_metadata_value,
351 text_t metadata_value_filter,
352 text_tmap classifier_options, cgiargsclass &args,
353 recptproto *collectproto, browsermapclass *browsers,
354 displayclass &disp, outconvertclass &outconvert,
355 ostream &textout, ostream &logout)
356{
357 // Get all the metadata values for the specified element that match the filter
358 text_t metadata_element_name = classifier_options["metadata_element_name"];
359 FilterResponse_t metadata_values_response;
360 bool request_success = get_metadata_values (metadata_element_name, metadata_value_filter, "", args["c"], collectproto, metadata_values_response, logout);
361
362 // If the request failed then it's probably because the collection isn't using an SQL infodbtype
363 if (request_success == false)
364 {
365 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";
366 return "";
367 }
368
369 // Check some metadata values were returned
370 if (metadata_values_response.docInfo.empty())
371 {
372 return "";
373 }
374
375 // After processing any hierarchical metadata values we're left with the hlist classifer nodes
376 map<text_t, int, lttext_t> hlist_classifier_nodes;
377 ResultDocInfo_tarray::iterator metadata_value_iterator = metadata_values_response.docInfo.begin();
378 while (metadata_value_iterator != metadata_values_response.docInfo.end())
379 {
380 text_t metadata_value = (*metadata_value_iterator).OID;
381
382 // If we're not at the top-level we need to remove the current position from the metadata values
383 if (starts_with(metadata_value, classifier_node_metadata_value + "|"))
384 {
385 metadata_value = substr(metadata_value.begin() + (classifier_node_metadata_value + "|").size(), metadata_value.end());
386 }
387
388 // Is this metadata value hierarchical?
389 text_t::iterator hierarchy_split_position = findchar(metadata_value.begin(), metadata_value.end(), '|');
390 if (hierarchy_split_position != metadata_value.end())
391 {
392 // Yes, so use the first part of the hierarchy only
393 metadata_value = substr(metadata_value.begin(), hierarchy_split_position);
394 }
395
396 // Create a node for this metadata value if we haven't seen it before
397 if (hlist_classifier_nodes.find(metadata_value) == hlist_classifier_nodes.end())
398 {
399 hlist_classifier_nodes[metadata_value] = 0;
400 }
401
402 // Increment the occurrence count
403 hlist_classifier_nodes[metadata_value] += (*metadata_value_iterator).result_num;
404
405 metadata_value_iterator++;
406 }
407
408 // If no classifier node has been specified automatically go to the first hlist node
409 if (args["dcn"] == parent_classifier_node_OID)
410 {
411 args["dcn"] = (*hlist_classifier_nodes.begin()).first;
412 }
413
414 // Add the necessary metadata to the hlist classifier nodes
415 text_t selected_hlist_node_OID = "";
416 FilterResponse_t hlist_classifier_nodes_response;
417 map<text_t, int, lttext_t>::iterator hlist_classifier_nodes_iterator = hlist_classifier_nodes.begin();
418 while (hlist_classifier_nodes_iterator != hlist_classifier_nodes.end())
419 {
420 text_t hlist_classifier_node_OID = (*hlist_classifier_nodes_iterator).first;
421
422 // Is this the hlist node that is currently selected?
423 if (starts_with (args["dcn"], hlist_classifier_node_OID))
424 {
425 selected_hlist_node_OID = hlist_classifier_node_OID;
426 }
427
428 // Add the necessary metadata required to display the hlist nodes correctly
429 ResultDocInfo_t hlist_classifier_node;
430 hlist_classifier_node.OID = hlist_classifier_node_OID;
431 hlist_classifier_node.metadata["doctype"].values.push_back ("classify");
432 hlist_classifier_node.metadata["haschildren"].values.push_back ("1");
433 hlist_classifier_node.metadata["numleafdocs"].values.push_back ("?"); // We can't determine this without more database requests
434 hlist_classifier_node.metadata["Title"].values.push_back (hlist_classifier_node_OID);
435 hlist_classifier_nodes_response.docInfo.push_back (hlist_classifier_node);
436
437 hlist_classifier_nodes_iterator++;
438 }
439
440 // Display the hlist nodes
441 display_classifier_nodes (hlist_classifier_nodes_response, "HList", 0, args, collectproto, browsers, disp, outconvert, textout, logout);
442
443 return selected_hlist_node_OID;
444}
445
446
[16061]447void dynamicclassifieraction::output_upper_classifier_nodes (text_t root_classifier_node_OID,
[16095]448 text_tlist upper_classifier_node_labels,
[16061]449 int& classifier_node_indent,
450 text_tmap classifier_options, cgiargsclass &args,
451 recptproto *collectproto, browsermapclass *browsers,
452 displayclass &disp, outconvertclass &outconvert,
453 ostream &textout, ostream &logout)
[15949]454{
[16095]455 // Display the upper classifier nodes
456 text_t upper_classifier_node_OID = root_classifier_node_OID;
457 text_tlist::iterator upper_classifier_node_labels_iterator = upper_classifier_node_labels.begin();
458 while (upper_classifier_node_labels_iterator != upper_classifier_node_labels.end())
[15768]459 {
[16095]460 upper_classifier_node_OID += (upper_classifier_node_OID != "" ? "|" : "");
461 upper_classifier_node_OID += *upper_classifier_node_labels_iterator;
[16096]462
463 ResultDocInfo_t upper_classifier_node;
464 upper_classifier_node.OID = upper_classifier_node_OID;
465 upper_classifier_node.metadata["doctype"].values.push_back ("classify");
466 upper_classifier_node.metadata["haschildren"].values.push_back ("1");
467 upper_classifier_node.metadata["numleafdocs"].values.push_back ("?"); // We can't determine this without more database requests
468 upper_classifier_node.metadata["Title"].values.push_back (*upper_classifier_node_labels_iterator);
469
470 FilterResponse_t upper_classifier_node_response;
471 upper_classifier_node_response.docInfo.push_back(upper_classifier_node);
[16107]472 display_classifier_nodes (upper_classifier_node_response, "VList", classifier_node_indent, args, collectproto, browsers, disp, outconvert, textout, logout);
[16055]473 classifier_node_indent++;
[15807]474
[16095]475 upper_classifier_node_labels_iterator++;
[15949]476 }
[16057]477}
[15949]478
[15953]479
[16057]480void dynamicclassifieraction::output_child_classifier_nodes (text_t classifier_node_OID,
[16061]481 text_t classifier_node_metadata_value,
[16057]482 text_t metadata_value_filter,
483 int& classifier_node_indent,
484 text_tmap classifier_options, cgiargsclass &args,
485 recptproto *collectproto, browsermapclass *browsers,
486 displayclass &disp, outconvertclass &outconvert,
487 ostream &textout, ostream &logout)
488{
489 // Get all the metadata values for the specified element that match the filter
490 text_t metadata_element_name = classifier_options["metadata_element_name"];
491 FilterResponse_t metadata_values_response;
492 bool request_success = get_metadata_values (metadata_element_name, metadata_value_filter, "", args["c"], collectproto, metadata_values_response, logout);
493
494 // If the request failed then it's probably because the collection isn't using an SQL infodbtype
495 if (request_success == false)
496 {
497 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";
498 return;
499 }
500
[16058]501 // After processing any hierarchical metadata values we're left with the child classifer nodes
502 map<text_t, int, lttext_t> child_classifier_nodes;
503 ResultDocInfo_tarray::iterator metadata_value_iterator = metadata_values_response.docInfo.begin();
504 while (metadata_value_iterator != metadata_values_response.docInfo.end())
[15949]505 {
[16004]506 text_t metadata_value = (*metadata_value_iterator).OID;
507
508 // If we're not at the top-level we need to remove the current position from the metadata values
[16061]509 if (starts_with(metadata_value, classifier_node_metadata_value + "|"))
[16004]510 {
[16061]511 metadata_value = substr(metadata_value.begin() + (classifier_node_metadata_value + "|").size(), metadata_value.end());
[16004]512 }
513
514 // Is this metadata value hierarchical?
515 text_t::iterator hierarchy_split_position = findchar(metadata_value.begin(), metadata_value.end(), '|');
516 if (hierarchy_split_position != metadata_value.end())
517 {
518 // Yes, so use the first part of the hierarchy only
519 metadata_value = substr(metadata_value.begin(), hierarchy_split_position);
520 }
521
522 // Create a node for this metadata value if we haven't seen it before
[16058]523 if (child_classifier_nodes.find(metadata_value) == child_classifier_nodes.end())
[16004]524 {
[16058]525 child_classifier_nodes[metadata_value] = 0;
[16004]526 }
527
528 // Increment the occurrence count
[16058]529 child_classifier_nodes[metadata_value] += (*metadata_value_iterator).result_num;
[16004]530
531 metadata_value_iterator++;
532 }
533
[16112]534 // Add the necessary metadata to the child classifier nodes
[16097]535 FilterResponse_t child_classifier_nodes_response;
[16058]536 map<text_t, int, lttext_t>::iterator child_classifier_nodes_iterator = child_classifier_nodes.begin();
537 while (child_classifier_nodes_iterator != child_classifier_nodes.end())
538 {
539 text_t child_classifier_node_OID = (*child_classifier_nodes_iterator).first;
540 if (classifier_node_OID != "")
541 {
542 child_classifier_node_OID = classifier_node_OID + "|" + child_classifier_node_OID;
543 }
[16004]544
[16097]545 ResultDocInfo_t child_classifier_node;
546 child_classifier_node.OID = child_classifier_node_OID;
547 child_classifier_node.metadata["doctype"].values.push_back ("classify");
548 child_classifier_node.metadata["haschildren"].values.push_back ("1");
549 child_classifier_node.metadata["numleafdocs"].values.push_back ((*child_classifier_nodes_iterator).second);
550 child_classifier_node.metadata["Title"].values.push_back ((*child_classifier_nodes_iterator).first);
551 child_classifier_nodes_response.docInfo.push_back (child_classifier_node);
[16004]552
[16097]553 child_classifier_nodes_iterator++;
[15949]554 }
555
[16112]556 // Display the child classifier nodes
[16107]557 display_classifier_nodes (child_classifier_nodes_response, "VList", classifier_node_indent, args, collectproto, browsers, disp, outconvert, textout, logout);
[15949]558}
559
560
[16096]561void dynamicclassifieraction::display_classifier_nodes (FilterResponse_t classifier_nodes_response,
[16107]562 text_t classifier_nodes_type,
563 int classifier_nodes_indent,
[16096]564 cgiargsclass &args, recptproto *collectproto,
565 browsermapclass *browsers, displayclass &disp,
566 outconvertclass &outconvert, ostream &textout,
567 ostream &logout)
568{
[16097]569 // Check there are some classifier nodes to display
570 if (classifier_nodes_response.docInfo.empty()) return;
571
[16096]572 // Get the format statement for this classifier if there is one, or use the browser's default otherwise
573 text_t formatstring;
[16107]574 browserclass *bptr = browsers->getbrowser (classifier_nodes_type);
[16096]575 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
[16107]576 if (!get_formatstring (args["dcl"], classifier_nodes_type, cinfo->format, formatstring))
[16096]577 {
578 formatstring = bptr->get_default_formatstring();
579 }
580 format_t *formatlistptr = new format_t();
581 text_tset metadata;
582 bool getParents = false;
583 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
584 bool use_table = is_table_content (formatlistptr);
585
586 // Display the classifier nodes
[16107]587 bptr->output_section_group (classifier_nodes_response, args, args["c"], classifier_nodes_indent, formatlistptr, use_table, metadata, getParents, collectproto, disp, outconvert, textout, logout);
[16096]588}
589
590
[16107]591void dynamicclassifieraction::display_document_nodes (FilterResponse_t documents_response,
592 int document_nodes_indent,
[16056]593 cgiargsclass &args, recptproto *collectproto,
594 browsermapclass *browsers, displayclass &disp,
595 outconvertclass &outconvert, ostream &textout,
596 ostream &logout)
[15949]597{
[16097]598 // Check there are some documents to display
599 if (documents_response.docInfo.empty()) return;
600
[16108]601 // Get the format statement for the document nodes if there is one, or use the browser's default otherwise
[15949]602 text_t formatstring;
[16108]603 browserclass *bptr = browsers->getbrowser ("VList");
[15949]604 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
[16108]605 if (!get_formatstring (args["dcl"], "DocumentNodes", cinfo->format, formatstring))
[15949]606 {
607 formatstring = bptr->get_default_formatstring();
608 }
609 format_t *formatlistptr = new format_t();
610 text_tset metadata;
611 bool getParents = false;
612 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
613 bool use_table = is_table_content (formatlistptr);
614
[16007]615 // Request the necessary metadata for displaying the documents
616 text_tarray document_OIDs;
617 ResultDocInfo_tarray::iterator document_iterator = documents_response.docInfo.begin();
618 while (document_iterator != documents_response.docInfo.end())
619 {
620 document_OIDs.push_back ((*document_iterator).OID);
621 document_iterator++;
622 }
623 FilterResponse_t document_nodes_response;
624 get_info (document_OIDs, args["c"], args["l"], metadata, getParents, collectproto, document_nodes_response, logout);
[15949]625
626 // Display the document nodes
[16007]627 bptr->output_section_group (document_nodes_response, args, args["c"], document_nodes_indent, formatlistptr, use_table, metadata, getParents, collectproto, disp, outconvert, textout, logout);
[15949]628}
Note: See TracBrowser for help on using the repository browser.