root/gsdl/trunk/src/recpt/dynamicclassifieraction.cpp @ 16114

Revision 16114, 27.5 KB (checked in by mdewsnip, 12 years ago)

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

  • Property svn:executable set to *
Line 
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"
27#include "recptprototools.h"
28
29
30dynamicclassifieraction::dynamicclassifieraction ()
31{
32  recpt = NULL;
33
34  cgiarginfo arg_ainfo;
35  arg_ainfo.shortname = "dcl";
36  arg_ainfo.longname = "dynamic classifier ID";
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);
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);
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
74// define all the macros which might be used by other actions to produce pages.
75void dynamicclassifieraction::define_external_macros (displayclass &disp, cgiargsclass &args,
76                              recptprotolistclass *protos, ostream &logout)
77{
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);
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{
122  // A valid collection server is vital
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
130  textout << outconvert << disp << "_dynamicclassifier:header_\n";
131  textout << outconvert << disp << "_dynamicclassifier:content_\n";
132
133  // Check a dynamic classifier ID has been specified
134  text_t arg_dcl = args["dcl"];
135  if (arg_dcl.empty())
136  {
137    textout << outconvert << disp << "Error: Missing dcl argument.\n";
138    textout << outconvert << disp << "_dynamicclassifier:footer_\n";
139    return true;
140  }
141
142  // Check the dynamic classifier ID is valid (ie. there is an entry in the collect.cfg file for it)
143  ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
144  if (cinfo->dynamic_classifiers.find(arg_dcl) == cinfo->dynamic_classifiers.end())
145  {
146    textout << outconvert << disp << "Error: Invalid dcl value \"" << arg_dcl << "\".\n";
147    textout << outconvert << disp << "_dynamicclassifier:footer_\n";
148    return true;
149  }
150
151  // Parse the classifier options from the specification
152  text_t classifier_specification = cinfo->dynamic_classifiers[arg_dcl];
153  text_tmap classifier_options = parse_classifier_options (classifier_specification, args);
154
155  // Output the "<ID>Header" format statement if there is one
156  text_t classifier_header_format_statement = "";
157  get_formatstring (arg_dcl + "Header", cinfo->format, classifier_header_format_statement);
158  textout << outconvert << disp << classifier_header_format_statement << "\n";
159
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
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
180  text_t selected_grouping_node_OID = "";
181  if (!classifier_options["-group_using"].empty())
182  {
183    selected_grouping_node_OID = output_grouping_nodes (classifier_options, args, collectproto, browsers, disp, outconvert, textout, logout);
184    classifier_node_OID = args["dcn"];  // args["dcn"] may have been modified by output_grouping_nodes()
185  }
186
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
198  // Simple case at the top level: just output the child classifier nodes
199  if (classifier_node_OID == selected_grouping_node_OID)
200  {
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);
203  }
204
205  // More complex case below the top level
206  else
207  {
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    }
214
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
226    // Determine the parent classifier node labels
227    text_tlist parent_classifier_node_labels;
228    splitchar(classifier_node_OID_sans_hlists.begin(), classifier_node_OID_sans_hlists.end(), '|', parent_classifier_node_labels);
229
230    // Output the parent classifier nodes and the current classifier node
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);
232
233    // Output the child classifier nodes
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);
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);
246  }
247
248  // Output the "<ID>Footer" format statement if there is one
249  text_t classifier_footer_format_statement = "";
250  get_formatstring (arg_dcl + "Footer", cinfo->format, classifier_footer_format_statement);
251  textout << outconvert << disp << classifier_footer_format_statement << "\n";
252
253  textout << outconvert << disp << "_dynamicclassifier:footer_\n";
254  return true;
255}
256
257
258text_tmap dynamicclassifieraction::parse_classifier_options (text_t classifier_specification, cgiargsclass &args)
259{
260  text_tmap classifier_options;
261
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
289  return classifier_options;
290}
291
292
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
323  // Add the necessary metadata to the grouping nodes
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?
329    if (starts_with (args["dcn"], (*grouping_node_iterator).OID))
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
343  display_classifier_nodes (grouping_nodes_response, "HList", 0, args, collectproto, browsers, disp, outconvert, textout, logout);
344
345  return selected_grouping_node_OID;
346}
347
348
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
447void dynamicclassifieraction::output_upper_classifier_nodes (text_t root_classifier_node_OID,
448                                 text_tlist upper_classifier_node_labels,
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)
454{
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())
459  {
460    upper_classifier_node_OID += (upper_classifier_node_OID != "" ? "|" : "");
461    upper_classifier_node_OID += *upper_classifier_node_labels_iterator;
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);
472    display_classifier_nodes (upper_classifier_node_response, "VList", classifier_node_indent, args, collectproto, browsers, disp, outconvert, textout, logout);
473    classifier_node_indent++;
474
475    upper_classifier_node_labels_iterator++;
476  }
477}
478
479
480void dynamicclassifieraction::output_child_classifier_nodes (text_t classifier_node_OID,
481                                 text_t classifier_node_metadata_value,
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
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())
505  {
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
509    if (starts_with(metadata_value, classifier_node_metadata_value + "|"))
510    {
511      metadata_value = substr(metadata_value.begin() + (classifier_node_metadata_value + "|").size(), metadata_value.end());
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
523    if (child_classifier_nodes.find(metadata_value) == child_classifier_nodes.end())
524    {
525      child_classifier_nodes[metadata_value] = 0;
526    }
527
528    // Increment the occurrence count
529    child_classifier_nodes[metadata_value] += (*metadata_value_iterator).result_num;
530
531    metadata_value_iterator++;
532  }
533
534  // Add the necessary metadata to the child classifier nodes
535  FilterResponse_t child_classifier_nodes_response;
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    }
544
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);
552
553    child_classifier_nodes_iterator++;
554  }
555
556  // Display the child classifier nodes
557  display_classifier_nodes (child_classifier_nodes_response, "VList", classifier_node_indent, args, collectproto, browsers, disp, outconvert, textout, logout);
558}
559
560
561void dynamicclassifieraction::display_classifier_nodes (FilterResponse_t classifier_nodes_response,
562                                text_t classifier_nodes_type,
563                            int classifier_nodes_indent,
564                            cgiargsclass &args, recptproto *collectproto,
565                            browsermapclass *browsers, displayclass &disp,
566                            outconvertclass &outconvert, ostream &textout,
567                            ostream &logout)
568{
569  // Check there are some classifier nodes to display
570  if (classifier_nodes_response.docInfo.empty()) return;
571
572  // Get the format statement for this classifier if there is one, or use the browser's default otherwise
573  text_t formatstring;
574  browserclass *bptr = browsers->getbrowser (classifier_nodes_type);
575  ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
576  if (!get_formatstring (args["dcl"], classifier_nodes_type, cinfo->format, formatstring))
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
587  bptr->output_section_group (classifier_nodes_response, args, args["c"], classifier_nodes_indent, formatlistptr, use_table, metadata, getParents, collectproto, disp, outconvert, textout, logout);
588}
589
590
591void dynamicclassifieraction::display_document_nodes (FilterResponse_t documents_response,
592                              int document_nodes_indent,
593                              cgiargsclass &args, recptproto *collectproto,
594                              browsermapclass *browsers, displayclass &disp,
595                              outconvertclass &outconvert, ostream &textout,
596                              ostream &logout)
597{
598  // Check there are some documents to display
599  if (documents_response.docInfo.empty()) return;
600
601  // Get the format statement for the document nodes if there is one, or use the browser's default otherwise
602  text_t formatstring;
603  browserclass *bptr = browsers->getbrowser ("VList");
604  ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
605  if (!get_formatstring (args["dcl"], "DocumentNodes", cinfo->format, formatstring))
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
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);
625
626  // Display the document nodes
627  bptr->output_section_group (document_nodes_response, args, args["c"], document_nodes_indent, formatlistptr, use_table, metadata, getParents, collectproto, disp, outconvert, textout, logout);
628}
Note: See TracBrowser for help on using the browser.