source: main/trunk/greenstone2/runtime-src/src/colservr/filter.cpp@ 27064

Last change on this file since 27064 was 16310, checked in by davidb, 16 years ago

Introduction of 'collecthome' which parallels 'gsdlhome' to allow the toplevel collect folder to be outside of the gsdlhome area

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
Line 
1/**********************************************************************
2 *
3 * filter.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 "filter.h"
27#include "fileutil.h"
28#include <assert.h>
29
30#include <iostream>
31using namespace std;
32
33
34// default constructor does nothing
35filterclass::filterclass () {
36}
37
38// default destructor does nothing
39filterclass::~filterclass () {
40}
41
42// configure should be called once for each configuration line
43// default configures the default filter options
44void filterclass::configure (const text_t &key, const text_tarray &cfgline) {
45 if (cfgline.size() >= 1) {
46 const text_t &value = cfgline[0];
47
48 if (key == "collection") collection = value;
49 else if (key == "collectdir") collectdir = value;
50 else if (key == "gsdlhome") gsdlhome = value;
51 else if (key == "collecthome") collecthome = value;
52 else if (key == "gdbmhome") dbhome = value;
53 else if ((key == "filteroptdefault") && (cfgline.size() == 2)) {
54 // see if this filter has an option with this name
55 FilterOption_tmap::iterator thisfilteroption =
56 filterOptions.find(cfgline[0]);
57 if (thisfilteroption != filterOptions.end())
58 (*thisfilteroption).second.defaultValue = cfgline[1];
59 }
60 }
61}
62
63text_t filterclass::resolve_db_filename(const text_t& idx,
64 const text_t& file_ext)
65{
66 text_t resolved_filename;
67
68 if (gsdlhome==dbhome) {
69 // dbhome has defaulted to gsdlhome which we take to means the
70 // database has been specifically moved out of gsdlhome area.
71 // => it should be whereever collecthome is set to
72 resolved_filename = filename_cat(collecthome, collection, "index", "text", idx);
73 }
74 else {
75 // dbhome is explicitly set to something other than gsdlhome
76 // => use dbhome
77 resolved_filename = filename_cat(dbhome, "collect", collection, "index", "text", idx);
78 }
79
80 resolved_filename += file_ext;
81
82 return resolved_filename;
83}
84
85
86// init should be called after all the configuration is done but
87// before any other methods are called
88// default checks all the filter option defaults
89bool filterclass::init (ostream &/*logout*/) {
90 // check all the filter defaults
91 FilterOption_tmap::iterator filteroption_here = filterOptions.begin();
92 FilterOption_tmap::iterator filteroption_end = filterOptions.end();
93 while (filteroption_here != filteroption_end) {
94 (*filteroption_here).second.check_defaultValue ();
95
96 ++filteroption_here;
97 }
98
99 if (collecthome.empty()) collecthome = filename_cat(gsdlhome,"collect");
100 if (dbhome.empty()) dbhome = gsdlhome;
101
102 // get the collection directory name
103 if (collectdir.empty()) {
104 collectdir = filename_cat (collecthome, collection);
105 }
106
107 return true;
108}
109
110// returns the name of this filter
111// default returns "NullFilter"
112text_t filterclass::get_filter_name () {
113 return "NullFilter";
114}
115
116// returns the current filter options
117void filterclass::get_filteroptions (InfoFilterOptionsResponse_t &response,
118 comerror_t &err, ostream &/*logout*/) {
119 response.clear();
120 response.filterOptions = filterOptions;
121 err = noError;
122}
123
124// default returns nothing
125void filterclass::filter (const FilterRequest_t &request,
126 FilterResponse_t &response,
127 comerror_t &err, ostream &/*logout*/) {
128 ResultDocInfo_t resultdoc;
129
130 response.clear();
131
132 if ((request.filterResultOptions & FROID) ||
133 (request.filterResultOptions & FRmetadata)) {
134 // copy the OIDs from the request to the response
135 text_tarray::const_iterator here = request.docSet.begin();
136 text_tarray::const_iterator end = request.docSet.end();
137 while (here != end) {
138 resultdoc.OID = (*here);
139 response.docInfo.push_back(resultdoc);
140
141 ++here;
142 }
143 }
144
145 response.numDocs = response.docInfo.size();
146 response.isApprox = Exact;
147 err = noError;
148}
149
150
151bool operator==(const filterptr &x, const filterptr &y) {
152 return (x.f == y.f);
153}
154
155bool operator<(const filterptr &x, const filterptr &y) {
156 return (x.f < y.f);
157}
158
159
160// thefilter remains the property of the calling code but
161// should not be deleted until it is removed from this list.
162void filtermapclass::addfilter (filterclass *thefilter) {
163 // can't add a null filter
164 assert (thefilter != NULL);
165 if (thefilter == NULL) return;
166
167 // can't add an filter with no name
168 assert (!(thefilter->get_filter_name()).empty());
169 if ((thefilter->get_filter_name()).empty()) return;
170
171 filterptr fptr;
172 fptr.f = thefilter;
173 filterptrs[thefilter->get_filter_name()] = fptr;
174}
175
176// getfilter will return NULL if the filter could not be found
177filterclass *filtermapclass::getfilter (const text_t &key) {
178 // can't find an filter with no name
179 assert (!key.empty());
180 if (key.empty()) return NULL;
181
182 iterator here = filterptrs.find (key);
183 if (here == filterptrs.end()) return NULL;
184
185 return (*here).second.f;
186}
187
188
189
190
191// some useful functions for dealing with document sets
192
193// returns -1 if t1 is a child of t2
194// returns 0 if t1 and t2 are not parent-child related
195// returns 1 if t1 is a parent of t2
196int child_compare (const text_t &t1, const text_t &t2) {
197 text_t::const_iterator t1_here = t1.begin();
198 text_t::const_iterator t1_end = t1.end();
199 text_t::const_iterator t2_here = t2.begin();
200 text_t::const_iterator t2_end = t2.end();
201
202 while ((t1_here != t1_end) && (t2_here != t2_end)) {
203 if (*t1_here != *t2_here) return 0; // unrelated
204 ++t1_here;
205 ++t2_here;
206 }
207
208 if ((t1_here == t1_end) && (t2_here == t2_end)) return 0; // equal
209 if (t1_here != t1_end) {
210 if (*t1_here == '.') return -1; // t1 is child
211 else return 0; // unrelated
212 }
213
214 if (t2_here != t2_end) {
215 if (*t2_here == '.') return 1; // t2 is child
216 else return 0; // unrelated
217 }
218
219 return 0; // shouldn't get here...
220}
221
222// intersect places the result in set1
223void intersect (text_tset &set1, const text_tset &set2) {
224 text_tset resultset;
225 int childcomp = 0;
226
227 text_tset::const_iterator set1_here = set1.begin();
228 text_tset::const_iterator set1_end = set1.end();
229 text_tset::const_iterator set2_here = set2.begin();
230 text_tset::const_iterator set2_end = set2.end();
231 while ((set1_here != set1_end) && (set2_here != set2_end)) {
232 if (*set1_here == *set2_here) {
233 // equal
234 resultset.insert (*set1_here);
235 ++set1_here;
236 ++set2_here;
237
238 } else if ((childcomp=child_compare(*set1_here, *set2_here)) != 0) {
239 if (childcomp < 0) {
240 // set1_here is child
241 resultset.insert (*set1_here);
242 ++set1_here;
243 } else {
244 // set2_here is child
245 resultset.insert (*set2_here);
246 ++set2_here;
247 }
248
249 } else if (*set1_here < *set2_here) {
250 // set1 is less
251 ++set1_here;
252
253 } else {
254 // set2 is less
255 ++set2_here;
256 }
257 }
258
259 set1 = resultset;
260}
261
262void intersect (text_tarray &set1, const text_tset &set2) {
263 text_tarray resultset;
264
265 text_tarray::const_iterator set1_here = set1.begin();
266 text_tarray::const_iterator set1_end = set1.end();
267
268 while (set1_here != set1_end) {
269 if (in_set (set2, *set1_here))
270 resultset.push_back (*set1_here);
271 ++set1_here;
272 }
273 set1 = resultset;
274}
275
276void intersect (text_tarray &set1, const text_tarray &set2) {
277 text_tarray resultset;
278
279 text_tarray::const_iterator set1_here = set1.begin();
280 text_tarray::const_iterator set1_end = set1.end();
281
282 while (set1_here != set1_end) {
283 if (in_set (set2, *set1_here))
284 resultset.push_back (*set1_here);
285 ++set1_here;
286 }
287 set1 = resultset;
288}
289
290// tests to see if el is in set
291bool in_set (const text_tset &set1, const text_t &el) {
292 text_t::const_iterator here = el.begin();
293 text_t::const_iterator end = el.end();
294 text_t tryel, tryel_add;
295 bool first = true;
296
297 // the element is in the set if any of its parents are
298 // in the set
299 do {
300 // get next possible element to try
301 here = getdelimitstr (here, end, '.', tryel_add);
302 if (!first) tryel += ".";
303 first = false;
304 tryel += tryel_add;
305
306 // see if this element is in the set
307 if (set1.find(tryel) != set1.end()) return true;
308 } while (here != end);
309
310 return false;
311}
312
313bool in_set (const text_tarray &set1, const text_t &el) {
314 text_t::const_iterator here = el.begin();
315 text_t::const_iterator end = el.end();
316 text_t tryel, tryel_add;
317 bool first = true;
318
319 // the element is in the set if any of its parents are
320 // in the set
321 do {
322 // get next possible element to try
323 here = getdelimitstr (here, end, '.', tryel_add);
324 if (!first) tryel += ".";
325 first = false;
326 tryel += tryel_add;
327
328 // see if this element is in the set
329 text_tarray::const_iterator h = set1.begin();
330 text_tarray::const_iterator e = set1.end();
331 while (h != e) {
332 if (*h == tryel) return true;
333 ++h;
334 }
335 } while (here != end);
336
337 return false;
338}
Note: See TracBrowser for help on using the repository browser.