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

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

(Adding new DB support) Changed lots of "gdbm"s to "db"s, in preparation for adding new DB types.

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