source: main/trunk/greenstone2/runtime-src/src/protocol/recptprototools.cpp@ 22080

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

Modifying get_metadata_values() and get_documents_with_metadata_value() to take an array of metadata elements, rather than just one metadata element. This allows building a dynamic classifier on multiple metadata elements.

  • Property svn:executable set to *
File size: 10.1 KB
Line 
1/**********************************************************************
2 *
3 * recptprototools.cpp --
4 * Copyright (C) 1999-2008 The New Zealand Digital Library Project
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 "recptprototools.h"
27#include <assert.h>
28
29
30// get_info does a protocol call and returns (in response) the metadata
31// associated with OID. Metadata should be loaded with whatever
32// metadata fields are to be requested.
33
34bool get_info (const text_t &OID, const text_t &collection, const text_t &lang,
35 const text_tset &metadata, bool getParents,
36 recptproto *collectproto, FilterResponse_t &response,
37 ostream &logout)
38{
39 response.clear();
40
41 comerror_t err = noError;
42 FilterRequest_t request;
43 request.clear();
44
45 request.filterName = "NullFilter";
46 request.filterLang = lang;
47 request.filterResultOptions = FRmetadata;
48 request.getParents = getParents;
49 request.fields = metadata;
50 request.docSet.push_back (OID);
51 assert (collectproto != NULL);
52
53 collectproto->filter (collection, request, response, err, logout);
54 if (err != noError)
55 {
56 outconvertclass text_t2ascii;
57 logout << text_t2ascii
58 << "Error: call to filter failed for " << OID
59 << " in recptprototools::get_info ("
60 << get_comerror_string (err) << ")\n";
61 return false;
62 }
63
64 return true;
65}
66
67
68// overloaded, to allow "custom" filter options.
69bool get_info (const text_t &OID, const text_t &collection, const text_t &lang,
70 const text_tset &metadata, const OptionValue_tarray &options,
71 bool getParents,
72 recptproto *collectproto, FilterResponse_t &response,
73 ostream &logout)
74{
75 response.clear();
76
77 comerror_t err = noError;
78 FilterRequest_t request;
79
80 request.filterName = "NullFilter";
81 request.filterLang = lang;
82 request.filterResultOptions = FRmetadata;
83 request.getParents = getParents;
84 request.filterOptions = options;
85 request.fields = metadata;
86 request.docSet.push_back (OID);
87
88 assert (collectproto != NULL);
89 collectproto->filter (collection, request, response, err, logout);
90 if (err != noError)
91 {
92 outconvertclass text_t2ascii;
93 logout << text_t2ascii
94 << "Error: call to filter failed for " << OID
95 << " in recptprototools::get_info ("
96 << get_comerror_string (err) << ")\n";
97 return false;
98 }
99
100 return true;
101}
102
103
104bool get_info (const text_tarray &OIDs, const text_t &collection, const text_t &lang,
105 const text_tset &metadata, bool getParents,
106 recptproto *collectproto, FilterResponse_t &response,
107 ostream &logout)
108{
109 response.clear();
110 if (OIDs.empty()) return true;
111
112 comerror_t err = noError;
113 FilterRequest_t request;
114
115 request.filterName = "NullFilter";
116 request.filterLang = lang;
117 request.filterResultOptions = FRmetadata;
118 request.getParents = getParents;
119 request.fields = metadata;
120
121 request.docSet = OIDs;
122
123 collectproto->filter (collection, request, response, err, logout);
124 if (err != noError)
125 {
126 outconvertclass text_t2ascii;
127 logout << text_t2ascii
128 << "Error: call to filter failed in recptprototools::get_info ("
129 << get_comerror_string (err) << ")\n";
130 return false;
131 }
132
133 return true;
134}
135
136
137// has_children returns true if OID has children
138bool has_children (const text_t &OID, const text_t &collection, const text_t &lang,
139 recptproto *collectproto, ostream &logout) {
140
141 FilterResponse_t response;
142 text_tset metadata;
143 metadata.insert ("haschildren");
144
145 if (get_info (OID, collection, lang, metadata, false, collectproto, response, logout))
146 {
147 if (response.docInfo[0].metadata["haschildren"].values[0] == "1")
148 {
149 return true;
150 }
151 }
152
153 return false;
154}
155
156
157// get_children does a protocol call and returns (in response) the OIDs and
158// metadata of all the children of OID. The metadata set should be loaded
159// with whatever metadata fields are to be requested.
160
161bool get_children (const text_t &OID, const text_t &collection, const text_t &lang,
162 const text_tset &metadata, bool getParents,
163 recptproto *collectproto, FilterResponse_t &response,
164 ostream &logout)
165{
166 response.clear();
167
168 comerror_t err = noError;
169 FilterRequest_t request;
170 OptionValue_t option;
171
172 option.name = "ParentNode";
173 option.value = OID;
174 request.filterOptions.push_back (option);
175 request.filterName = "BrowseFilter";
176 request.filterLang = lang;
177 request.filterResultOptions = FROID;
178
179 // Efficiency improvement: only get the filter to retrieve metadata if some has been requested
180 // Otherwise, the filter makes an unnecessary request to the database for each child node
181 // By Michael Dewsnip, DL Consulting Ltd
182 if (metadata.size() > 0)
183 {
184 request.filterResultOptions |= FRmetadata;
185 }
186
187 request.fields = metadata;
188 request.getParents = getParents;
189
190 collectproto->filter (collection, request, response, err, logout);
191
192 if (err != noError)
193 {
194 outconvertclass text_t2ascii;
195 logout << text_t2ascii
196 << "Error: call to filter failed for " << OID
197 << " in recptprototools::get_children ("
198 << get_comerror_string (err) << ")\n";
199 return false;
200 }
201
202 return true;
203}
204
205
206static void recurse_contents (ResultDocInfo_t section, const bool &is_classify,
207 const text_t &collection, const text_t &lang,
208 const text_tset &metadata,
209 recptproto *collectproto, FilterResponse_t &response,
210 ostream &logout)
211{
212 int haschildren = section.metadata["haschildren"].values[0].getint();
213 const text_t &doctype = section.metadata["doctype"].values[0];
214
215 if ((haschildren == 1) && ((!is_classify) || (doctype == "classify")))
216 {
217 FilterResponse_t tmp;
218 bool getParents = false;
219 get_children (section.OID, collection, lang, metadata, getParents, collectproto, tmp, logout);
220 ResultDocInfo_tarray::iterator thisdoc = tmp.docInfo.begin();
221 ResultDocInfo_tarray::iterator lastdoc = tmp.docInfo.end();
222 while (thisdoc != lastdoc)
223 {
224 response.docInfo.push_back (*thisdoc);
225 recurse_contents (*thisdoc, is_classify, collection, lang, metadata, collectproto, response, logout);
226 ++thisdoc;
227 }
228 }
229}
230
231
232// get_contents returns OIDs and metadata of all contents
233// below (and including) OID.
234void get_contents (const text_t &topOID, const bool &is_classify,
235 text_tset &metadata, const text_t &collection, const text_t &lang,
236 recptproto *collectproto, FilterResponse_t &response,
237 ostream &logout)
238{
239 if (topOID.empty()) return;
240 response.clear();
241
242 metadata.insert ("haschildren");
243 metadata.insert ("doctype");
244
245 // get topOIDs info
246 if (get_info (topOID, collection, lang, metadata, false, collectproto, response, logout))
247 {
248 recurse_contents (response.docInfo[0], is_classify, collection, lang, metadata, collectproto, response, logout);
249 }
250}
251
252
253bool get_metadata_values (const text_t metadata_elements, const text_t metadata_value_filter,
254 const text_t metadata_value_grouping_expression, const text_t &collection,
255 recptproto *collectproto, FilterResponse_t &response, ostream &logout)
256{
257 response.clear();
258
259 comerror_t err = noError;
260 FilterRequest_t request;
261 request.clear();
262
263 request.filterName = "SQLBrowseFilter";
264 request.requestParams = "GetMetadataValues";
265
266 OptionValue_t request_option;
267 request_option.name = "MetadataElements";
268 request_option.value = metadata_elements;
269 request.filterOptions.push_back (request_option);
270 request_option.name = "MetadataValueFilter";
271 request_option.value = metadata_value_filter;
272 request.filterOptions.push_back (request_option);
273 request_option.name = "MetadataValueGroupingExpression";
274 request_option.value = metadata_value_grouping_expression;
275 request.filterOptions.push_back (request_option);
276
277 assert (collectproto != NULL);
278 collectproto->filter (collection, request, response, err, logout);
279 if (err != noError)
280 {
281 outconvertclass text_t2ascii;
282 logout << text_t2ascii
283 << "Error: call to filter failed for " << metadata_elements
284 << " in recptprototools::get_metadata_values ("
285 << get_comerror_string (err) << ")\n";
286 return false;
287 }
288
289 return true;
290}
291
292
293bool get_documents_with_metadata_value (const text_t metadata_elements, const text_t metadata_value,
294 const text_t sort_by_metadata_element_name, const text_t &collection,
295 recptproto *collectproto, FilterResponse_t &response, ostream &logout)
296{
297 response.clear();
298
299 comerror_t err = noError;
300 FilterRequest_t request;
301 request.clear();
302
303 request.filterName = "SQLBrowseFilter";
304 request.requestParams = "GetDocumentsWithMetadataValue";
305
306 OptionValue_t request_option;
307 request_option.name = "MetadataElements";
308 request_option.value = metadata_elements;
309 request.filterOptions.push_back (request_option);
310 request_option.name = "MetadataValue";
311 request_option.value = metadata_value;
312 request.filterOptions.push_back (request_option);
313 request_option.name = "SortByMetadataElement";
314 request_option.value = sort_by_metadata_element_name;
315 request.filterOptions.push_back (request_option);
316
317 assert (collectproto != NULL);
318 collectproto->filter (collection, request, response, err, logout);
319 if (err != noError)
320 {
321 outconvertclass text_t2ascii;
322 logout << text_t2ascii
323 << "Error: call to filter failed for " << metadata_elements << " = " << metadata_value
324 << " in recptprototools::get_documents_with_metadata_value ("
325 << get_comerror_string (err) << ")\n";
326 return false;
327 }
328
329 return true;
330}
Note: See TracBrowser for help on using the repository browser.