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

Last change on this file since 308 was 249, checked in by sjboddie, 25 years ago

lots of stuff to do with getting documentaction working

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 7.0 KB
Line 
1/**********************************************************************
2 *
3 * filter.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * PUT COPYRIGHT NOTICE HERE
7 *
8 * $Id: filter.cpp 249 1999-04-30 02:00:48Z sjboddie $
9 *
10 *********************************************************************/
11
12/*
13 $Log$
14 Revision 1.5 1999/04/30 02:00:46 sjboddie
15 lots of stuff to do with getting documentaction working
16
17 Revision 1.4 1999/04/12 03:45:02 rjmcnab
18 Finished the query filter.
19
20 Revision 1.3 1999/04/06 22:20:30 rjmcnab
21 Got browsefilter working.
22
23 Revision 1.2 1999/03/31 23:44:46 rjmcnab
24 Altered the protocol so that the metadata is part of the filter.
25
26 Revision 1.1 1999/03/30 05:10:06 rjmcnab
27 Initial revision.
28
29 */
30
31
32#include "filter.h"
33#include "fileutil.h"
34#include <assert.h>
35
36
37// default constructor does nothing
38filterclass::filterclass () {
39}
40
41// default destructor does nothing
42filterclass::~filterclass () {
43}
44
45// configure should be called once for each configuration line
46// default configures the default filter options
47void filterclass::configure (const text_t &key, const text_tarray &cfgline) {
48 if (cfgline.size() >= 1) {
49 const text_t &value = cfgline[0];
50
51 if (key == "collection") collection = value;
52 else if (key == "collectdir") collectdir = value;
53 else if (key == "gsdlhome") gsdlhome = value;
54 else if ((key == "filteroptdefault") && (cfgline.size() == 2)) {
55 // see if this filter has an option with this name
56 FilterOption_tmap::iterator thisfilteroption =
57 filterOptions.find(cfgline[0]);
58 if (thisfilteroption != filterOptions.end())
59 (*thisfilteroption).second.defaultValue = cfgline[1];
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 // get the collection directory name
78 if (collectdir.empty()) {
79 collectdir = filename_cat (gsdlhome, "collect", collection);
80 }
81
82 return true;
83}
84
85// returns the name of this filter
86// default returns "NullFilter"
87text_t filterclass::get_filter_name () {
88 return "NullFilter";
89}
90
91// returns the current filter options
92void filterclass::get_filteroptions (InfoFilterOptionsResponse_t &response,
93 comerror_t &err, ostream &/*logout*/) {
94 response.clear();
95 response.filterOptions = filterOptions;
96 err = noError;
97}
98
99// default returns nothing
100void filterclass::filter (const FilterRequest_t &request,
101 FilterResponse_t &response,
102 comerror_t &err, ostream &/*logout*/) {
103 ResultDocInfo_t resultdoc;
104
105 response.clear();
106
107 if ((request.filterResultOptions & FROID) ||
108 (request.filterResultOptions & FRmetadata)) {
109 // copy the OIDs from the request to the response
110 text_tset::const_iterator here = request.docSet.begin();
111 text_tset::const_iterator end = request.docSet.end();
112 while (here != end) {
113 resultdoc.OID = (*here);
114 response.docInfo.push_back(resultdoc);
115
116 here++;
117 }
118 }
119
120 response.numDocs = response.docInfo.size();
121 response.isApprox = false;
122 err = noError;
123}
124
125
126
127// thefilter remains the property of the calling code but
128// should not be deleted until it is removed from this list.
129void filtermapclass::addfilter (filterclass *thefilter) {
130 // can't add a null filter
131 assert (thefilter != NULL);
132 if (thefilter == NULL) return;
133
134 // can't add an filter with no name
135 assert (!(thefilter->get_filter_name()).empty());
136 if ((thefilter->get_filter_name()).empty()) return;
137
138 filterptr fptr;
139 fptr.f = thefilter;
140 filterptrs[thefilter->get_filter_name()] = fptr;
141}
142
143// getfilter will return NULL if the filter could not be found
144filterclass *filtermapclass::getfilter (const text_t &key) {
145 // can't find an filter with no name
146 assert (!key.empty());
147 if (key.empty()) return NULL;
148
149 iterator here = filterptrs.find (key);
150 if (here == filterptrs.end()) return NULL;
151
152 return (*here).second.f;
153}
154
155
156
157
158// some useful functions for dealing with document sets
159
160// returns -1 if t1 is a child of t2
161// returns 0 if t1 and t2 are not parent-child related
162// returns 1 if t1 is a parent of t2
163int child_compare (const text_t &t1, const text_t &t2) {
164 text_t::const_iterator t1_here = t1.begin();
165 text_t::const_iterator t1_end = t1.end();
166 text_t::const_iterator t2_here = t2.begin();
167 text_t::const_iterator t2_end = t2.end();
168
169 while ((t1_here != t1_end) && (t2_here != t2_end)) {
170 if (*t1_here != *t2_here) return 0; // unrelated
171 t1_here++;
172 t2_here++;
173 }
174
175 if ((t1_here == t1_end) && (t2_here == t2_end)) return 0; // equal
176 if (t1_here != t1_end) {
177 if (*t1_here == '.') return -1; // t1 is child
178 else return 0; // unrelated
179 }
180
181 if (t2_here != t2_end) {
182 if (*t2_here == '.') return 1; // t2 is child
183 else return 0; // unrelated
184 }
185
186 return 0; // shouldn't get here...
187}
188
189// intersect places the result in set1
190void intersect (text_tset &set1, const text_tset &set2) {
191 text_tset resultset;
192 int childcomp = 0;
193
194 text_tset::const_iterator set1_here = set1.begin();
195 text_tset::const_iterator set1_end = set1.end();
196 text_tset::const_iterator set2_here = set2.begin();
197 text_tset::const_iterator set2_end = set2.end();
198 while ((set1_here != set1_end) && (set2_here != set2_end)) {
199 if (*set1_here == *set2_here) {
200 // equal
201 resultset.insert (*set1_here);
202 set1_here++;
203 set2_here++;
204
205 } else if ((childcomp=child_compare(*set1_here, *set2_here)) != 0) {
206 if (childcomp < 0) {
207 // set1_here is child
208 resultset.insert (*set1_here);
209 set1_here++;
210 } else {
211 // set2_here is child
212 resultset.insert (*set2_here);
213 set2_here++;
214 }
215
216 } else if (*set1_here < *set2_here) {
217 // set1 is less
218 set1_here++;
219
220 } else {
221 // set2 is less
222 set2_here++;
223 }
224 }
225
226 set1 = resultset;
227}
228
229void intersect (text_tarray &set1, const text_tset &set2) {
230 text_tarray resultset;
231
232 text_tarray::const_iterator set1_here = set1.begin();
233 text_tarray::const_iterator set1_end = set1.end();
234
235 while (set1_here != set1_end) {
236 if (in_set (set2, *set1_here))
237 resultset.push_back (*set1_here);
238 set1_here ++;
239 }
240 set1 = resultset;
241}
242
243
244// tests to see if el is in set
245bool in_set (const text_tset &set1, const text_t &el) {
246 text_t::const_iterator here = el.begin();
247 text_t::const_iterator end = el.begin();
248 text_t tryel, tryel_add;
249 bool first = true;
250
251 // the element is in the set if any of its parents are
252 // in the set
253 do {
254 // get next possible element to try
255 here = getdelimitstr (here, end, '.', tryel_add);
256 if (!first) tryel += ".";
257 first = false;
258 tryel += tryel_add;
259
260 // see if this element is in the set
261 if (set1.find(tryel) != set1.end()) return true;
262 } while (here != end);
263
264 return false;
265}
Note: See TracBrowser for help on using the repository browser.