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

Last change on this file since 31388 was 31388, checked in by ak19, 7 years ago

Second commit to do with implementing OAI deletion policy for GS2. This commit is only loosely related, as it shifts functions duplicated in source.h and filter.h (and cpp files) into the new colserver.h and cpp files for sharing.

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