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

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

(Adding new DB support) Changed a lot of "gdbmhome" to "dbhome".

  • 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(dbhome, "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.