source: main/tags/2.10/gsdl/src/colservr/filter.cpp@ 32704

Last change on this file since 32704 was 534, checked in by sjboddie, 25 years ago

added gpl notice

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