source: gsdl/trunk/src/colservr/browsefilter.cpp@ 15757

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

(Adding new DB support) Now uses the new dbclass::getfileextension() function to avoid having GDBM-specific filename extension code scattered around.

  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/**********************************************************************
2 *
3 * browsefilter.cpp --
4 * Copyright (C) 1999 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 "browsefilter.h"
27#include "fileutil.h"
28
29
30browsefilterclass::browsefilterclass () {
31 db_ptr = NULL;
32
33 // -- onePerQuery StartResults integer
34 FilterOption_t filtopt;
35 filtopt.name = "StartResults";
36 filtopt.type = FilterOption_t::integert;
37 filtopt.repeatable = FilterOption_t::onePerQuery;
38 filtopt.defaultValue = "1";
39 filtopt.validValues.push_back("1");
40 filtopt.validValues.push_back("10000");
41 filterOptions["StartResults"] = filtopt;
42
43 // -- onePerQuery EndResults integer
44 filtopt.clear();
45 filtopt.name = "EndResults";
46 filtopt.type = FilterOption_t::integert;
47 filtopt.repeatable = FilterOption_t::onePerQuery;
48 filtopt.defaultValue = "-1";
49 filtopt.validValues.push_back("-1");
50 filtopt.validValues.push_back("10000");
51 filterOptions["EndResults"] = filtopt;
52
53 // -- onePerQuery ParentNode string ("" will return the browsing available)
54 filtopt.clear();
55 filtopt.name = "ParentNode";
56 filtopt.type = FilterOption_t::stringt;
57 filtopt.repeatable = FilterOption_t::onePerQuery;
58 filtopt.defaultValue = g_EmptyText;
59 filterOptions["ParentNode"] = filtopt;
60}
61
62browsefilterclass::~browsefilterclass () {
63}
64
65void browsefilterclass::configure (const text_t &key, const text_tarray &cfgline) {
66 filterclass::configure (key, cfgline);
67 if (key == "indexstem") {
68 indexstem = cfgline[0];
69 }
70}
71
72bool browsefilterclass::init (ostream &logout) {
73 outconvertclass text_t2ascii;
74
75 if (!filterclass::init(logout)) return false;
76
77 if (db_ptr == NULL) {
78 // most likely a configuration problem
79 logout << text_t2ascii
80 << "configuration error: browsefilter contains a null dbclass\n\n";
81 return false;
82 }
83
84 if (indexstem.empty()) {
85 indexstem = collection;
86 }
87 // get the filename for the database and make sure it exists
88 db_filename = filename_cat(dbhome, "collect", collection, "index", "text", indexstem);
89 db_filename += db_ptr->getfileextension();
90 if (!file_exists(db_filename)) {
91 logout << text_t2ascii
92 << "warning: database \"" << db_filename << "\" does not exist\n\n";
93 // return false;
94 }
95
96 return true;
97}
98
99void browsefilterclass::filter (const FilterRequest_t &request,
100 FilterResponse_t &response,
101 comerror_t &err, ostream &logout) {
102 int numDocs = 0;
103 outconvertclass text_t2ascii;
104
105 response.clear ();
106 err = noError;
107 if (db_ptr == NULL) {
108 // most likely a configuration problem
109 logout << text_t2ascii
110 << "configuration error: browsefilter contains a null dbclass\n\n";
111 err = configurationError;
112 return;
113 }
114
115 // open the database
116 db_ptr->setlogout(&logout);
117 if (!db_ptr->opendatabase (db_filename, DB_READER, 100, false)) {
118 // most likely a system problem (we have already checked that the database exists)
119 logout << text_t2ascii
120 << "system problem: open on database \""
121 << db_filename << "\" failed\n\n";
122 err = systemProblem;
123 return;
124 }
125
126 // get the browse parameters
127 int startresults = filterOptions["StartResults"].defaultValue.getint();
128 int endresults = filterOptions["EndResults"].defaultValue.getint();
129 text_t parentnode = filterOptions["ParentNode"].defaultValue;
130 OptionValue_tarray::const_iterator options_here = request.filterOptions.begin();
131 OptionValue_tarray::const_iterator options_end = request.filterOptions.end();
132 while (options_here != options_end) {
133 if ((*options_here).name == "StartResults")
134 startresults = (*options_here).value.getint();
135 else if ((*options_here).name == "EndResults")
136 endresults = (*options_here).value.getint();
137 else if ((*options_here).name == "ParentNode")
138 parentnode = (*options_here).value;
139 else {
140 logout << text_t2ascii
141 << "warning: unknown browsefilter option \""
142 << (*options_here).name
143 << "\" ignored.\n\n";
144 }
145
146 ++options_here;
147 }
148
149 infodbclass info;
150
151 // translate any ".fc", ".pr" etc. stuff in the parentnode
152 parentnode = db_ptr->translate_OID (parentnode, info);
153
154 // adjust topmost browsing node
155 if (parentnode.empty()) parentnode = "browse";
156
157 // get the node
158 if ((request.filterResultOptions & FROID) ||
159 (request.filterResultOptions & FRmetadata)) {
160 if (!db_ptr->getinfo(parentnode, info)) {
161 // didn't find the node
162 logout << text_t2ascii
163 << "warning: lookup for node \"" << parentnode
164 << "\" failed for browsefilter.\n\n";
165 } else {
166 // found the node
167
168 // replace " with the parent node name and split the contains string
169 // into the result set
170 text_tarray resultset;
171 text_t tmptext;
172 text_t &contains = info["contains"];
173 text_t::iterator contains_here = contains.begin();
174 text_t::iterator contains_end = contains.end();
175 while (contains_here != contains_end) {
176 if (*contains_here == '"') tmptext += parentnode;
177 else if (*contains_here == ';') {
178 if (!tmptext.empty()) resultset.push_back (tmptext);
179 tmptext.clear();
180 } else tmptext.push_back(*contains_here);
181
182 ++contains_here;
183 }
184 // insert the last result in the set
185 if (!tmptext.empty()) resultset.push_back (tmptext);
186
187 text_tarray offset_resultset;
188 text_t &md_type = info["mdtype"];
189 if (!md_type.empty())
190 {
191 text_t &md_offset = info["mdoffset"];
192 if (!md_offset.empty())
193 {
194 text_t offsettext;
195
196 text_t::iterator offset_here = md_offset.begin();
197 text_t::iterator offset_end = md_offset.end();
198 while (offset_here != offset_end)
199 {
200 if (*offset_here == ';')
201 {
202 if (offsettext.empty())
203 {
204 offset_resultset.push_back ("0");
205 }
206 else
207 {
208 offset_resultset.push_back (offsettext);
209 }
210 offsettext.clear();
211 }
212 else
213 {
214 offsettext.push_back(*offset_here);
215 }
216
217 ++offset_here;
218 }
219 // insert the last result in the set
220 if (offsettext.empty())
221 {
222 offset_resultset.push_back ("0");
223 }
224 else
225 {
226 offset_resultset.push_back (offsettext);
227 }
228 }
229 else
230 {
231 // add 0 offset for each 'contains' entry
232 text_tarray::iterator result_here = resultset.begin();
233 text_tarray::iterator result_end = resultset.end();
234 while (result_here != result_end) {
235 offset_resultset.push_back("0");
236 ++result_here;
237 }
238 }
239
240 // do an intersection with the input set
241 if (!request.docSet.empty()) {
242
243 text_tarray intersect_resultset;
244 text_tarray intersect_offset_resultset;
245
246 text_tarray::const_iterator resultset_here = resultset.begin();
247 text_tarray::const_iterator resultset_end = resultset.end();
248 text_tarray::const_iterator offset_resultset_here = offset_resultset.begin();
249
250 while (resultset_here != resultset_end) {
251 if (in_set (request.docSet, *resultset_here))
252 {
253 intersect_resultset.push_back (*resultset_here);
254 intersect_offset_resultset.push_back (*offset_resultset_here);
255 }
256 ++resultset_here;
257 ++offset_resultset_here;
258 }
259 resultset = intersect_resultset;
260 offset_resultset = intersect_offset_resultset;
261 }
262 }
263 else
264 {
265 // do an intersection with the input set
266 if (!request.docSet.empty()) {
267 intersect (resultset, request.docSet);
268 }
269
270 // add 0 offset for each 'contains' entry
271 text_tarray::iterator result_here = resultset.begin();
272 text_tarray::iterator result_end = resultset.end();
273 while (result_here != result_end) {
274 offset_resultset.push_back("0");
275 ++result_here;
276 }
277 }
278
279 // create the response
280 numDocs = resultset.size();
281 int resultnum = 1;
282 ResultDocInfo_t resultdoc;
283 text_tarray::iterator result_here = resultset.begin();
284 text_tarray::iterator result_end = resultset.end();
285 text_tarray::iterator offset_result_here = offset_resultset.begin();
286
287 while (result_here != result_end) {
288 // if endresults is -1 get all results
289 if ((endresults != -1) && (resultnum > endresults)) break;
290 if (resultnum >= startresults) {
291 resultdoc.OID = (*result_here);
292 if (!md_type.empty())
293 {
294 resultdoc.classifier_metadata_type = md_type;
295 resultdoc.classifier_metadata_offset = offset_result_here->getint();
296 }
297 response.docInfo.push_back(resultdoc);
298 }
299
300 ++resultnum;
301 ++result_here;
302 if (!md_type.empty()) ++offset_result_here;
303 }
304 }
305 }
306
307 db_ptr->closedatabase(); // Important that local library doesn't leave any files open
308 response.numDocs = numDocs;
309 response.isApprox = Exact;
310}
Note: See TracBrowser for help on using the repository browser.