source: gsdl/trunk/src/colservr/filter.cpp@ 15587

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

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

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