source: trunk/gsdl/src/recpt/OIDtools.cpp@ 1347

Last change on this file since 1347 was 1347, checked in by jrm21, 24 years ago

merged z39.50 receptionist stuff into main trunk (along with the mgpp stuff)

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1/**********************************************************************
2 *
3 * OIDtools.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 "OIDtools.h"
27
28
29// returns (in top) the top level of OID (i.e. everything
30// up until the first dot)
31void get_top (const text_t &OID, text_t &top) {
32
33 top.clear();
34 if (OID.empty()) return;
35
36 text_t::const_iterator begin = OID.begin();
37 text_t::const_iterator end = OID.end();
38
39 top.appendrange (begin, findchar(begin, end, '.'));
40}
41
42
43// checks if OID is top level (i.e. contains no dots)
44bool is_top (const text_t &OID) {
45
46 if (OID.empty()) return true;
47
48 text_t::const_iterator here = OID.begin();
49 text_t::const_iterator end = OID.end();
50 here = findchar (here, end, '.');
51
52 if (here == end) return true;
53 return false;
54}
55
56
57// get_parents_array loads the parents array with all the parents of the
58// document or classification specified by OID (not including OID itself)
59void get_parents_array (const text_t &OID, text_tarray &parents) {
60
61 text_t::const_iterator here = OID.begin ();
62 text_t::const_iterator end = OID.end ();
63 text_t thisparent;
64
65 while (here != end) {
66 if (*here == '.') parents.push_back(thisparent);
67 thisparent.push_back(*here);
68 here ++;
69 }
70}
71
72
73// get_info does a protocol call and returns (in response) the metadata
74// associated with OID. Metadata should be loaded with whatever
75// metadata fields are to be requested.
76
77bool get_info (const text_t &OID, const text_t &collection,
78 const text_tset &metadata, bool getParents,
79 recptproto *collectproto, FilterResponse_t &response,
80 ostream &logout) {
81
82 response.clear();
83
84 comerror_t err;
85 FilterRequest_t request;
86
87 request.filterName = "NullFilter";
88 request.filterResultOptions = FRmetadata;
89 request.getParents = getParents;
90 request.fields = metadata;
91 request.docSet.push_back (OID);
92
93 collectproto->filter (collection, request, response, err, logout);
94 if (err != noError) {
95 outconvertclass text_t2ascii;
96 logout << text_t2ascii
97 << "Error: call to filter failed for " << OID
98 << " in OIDtools::get_info ("
99 << get_comerror_string (err) << ")\n";
100 return false;
101 }
102
103 return true;
104}
105
106// overloaded, to allow "custom" filter options.
107bool get_info (const text_t &OID, const text_t &collection,
108 const text_tset &metadata, const OptionValue_tarray &options,
109 bool getParents,
110 recptproto *collectproto, FilterResponse_t &response,
111 ostream &logout) {
112
113 response.clear();
114
115 comerror_t err;
116 FilterRequest_t request;
117
118 request.filterName = "NullFilter";
119 request.filterResultOptions = FRmetadata;
120 request.getParents = getParents;
121 request.filterOptions = options;
122 request.fields = metadata;
123 request.docSet.push_back (OID);
124
125 collectproto->filter (collection, request, response, err, logout);
126 if (err != noError) {
127 outconvertclass text_t2ascii;
128 logout << text_t2ascii
129 << "Error: call to filter failed for " << OID
130 << " in OIDtools::get_info ("
131 << get_comerror_string (err) << ")\n";
132 return false;
133 }
134
135 return true;
136}
137
138bool get_info (const text_tarray &OIDs, const text_t &collection,
139 const text_tset &metadata, bool getParents,
140 recptproto *collectproto, FilterResponse_t &response,
141 ostream &logout) {
142
143 response.clear();
144 if (OIDs.empty()) return true;
145
146 comerror_t err;
147 FilterRequest_t request;
148
149 request.filterName = "NullFilter";
150 request.filterResultOptions = FRmetadata;
151 request.getParents = getParents;
152 request.fields = metadata;
153
154 request.docSet = OIDs;
155
156 collectproto->filter (collection, request, response, err, logout);
157 if (err != noError) {
158 outconvertclass text_t2ascii;
159 logout << text_t2ascii
160 << "Error: call to filter failed in OIDtools::get_info ("
161 << get_comerror_string (err) << ")\n";
162 return false;
163 }
164
165 return true;
166}
167
168
169
170// has_children returns true if OID has children
171bool has_children (const text_t &OID, const text_t &collection,
172 recptproto *collectproto, ostream &logout) {
173
174 FilterResponse_t response;
175 text_tset metadata;
176 metadata.insert ("haschildren");
177
178 if (get_info (OID, collection, metadata, false, collectproto, response, logout)) {
179 if (response.docInfo[0].metadata["haschildren"].values[0] == "1")
180 return true;
181 }
182 return false;
183}
184
185
186// get_children does a protocol call and returns (in response) the OIDs and
187// metadata of all the children of OID. The metadata set should be loaded
188// with whatever metadata fields are to be requested.
189
190bool get_children (const text_t &OID, const text_t &collection,
191 const text_tset &metadata, bool getParents,
192 recptproto *collectproto, FilterResponse_t &response,
193 ostream &logout) {
194
195 response.clear();
196
197 comerror_t err;
198 FilterRequest_t request;
199 OptionValue_t option;
200
201 option.name = "ParentNode";
202 option.value = OID;
203 request.filterOptions.push_back (option);
204 request.filterName = "BrowseFilter";
205 request.filterResultOptions = FROID | FRmetadata;
206 request.fields = metadata;
207 request.getParents = getParents;
208
209 collectproto->filter (collection, request, response, err, logout);
210
211 if (err != noError) {
212 outconvertclass text_t2ascii;
213 logout << text_t2ascii
214 << "Error: call to filter failed for " << OID
215 << " in OIDtools::get_children ("
216 << get_comerror_string (err) << ")\n";
217 return false;
218 }
219 return true;
220}
221
222// get_parent returns the parent of the document or classification
223// specified by OID
224text_t get_parent (text_t OID) {
225
226 if (OID.empty() || is_top (OID)) return "";
227
228 text_t::const_iterator begin = OID.begin();
229 text_t::const_iterator here = (OID.end() - 1);
230
231 while (here >= begin) {
232 OID.pop_back();
233 if (*here == '.') break;
234 here --;
235 }
236 return OID;
237}
238
239// takes an OID like ".2 and replaces the " with parent
240void translate_parent (text_t &OID, const text_t &parent) {
241
242 text_t::const_iterator here = OID.begin();
243 text_t::const_iterator end = OID.end();
244 text_t temp;
245
246 while (here != end) {
247 if (*here == '"') temp += parent;
248 else temp.push_back (*here);
249 here ++;
250 }
251 OID = temp;
252}
253
254// shrink_parent does the opposite to translate_parent
255void shrink_parent (text_t &OID) {
256
257 text_tarray tmp;
258 splitchar (OID.begin(), OID.end(), '.', tmp);
259 OID = "\"." + tmp.back();
260}
261
262// checks if OID uses ".fc", ".lc", ".pr", ".ns",
263// or ".ps" syntax (first child, last child, parent,
264// next sibling, previous sibling)
265bool needs_translating (const text_t &OID) {
266
267 if (OID.size() < 4) return false;
268
269 text_t tail = substr (OID.end()-3, OID.end());
270 if (tail == ".fc" || tail == ".lc" || tail == ".pr" ||
271 tail == ".ns" || tail == ".ps") return true;
272
273 return false;
274}
275
276// strips the ".fc", ".lc", ".pr", ".ns",
277// or ".ps" suffix from the end of OID
278void strip_suffix (text_t &OID) {
279
280 text_t tail = substr (OID.end()-3, OID.end());
281 while (tail == ".fc" || tail == ".lc" || tail == ".pr" ||
282 tail == ".ns" || tail == ".ps") {
283 OID.erase (OID.end()-3, OID.end());
284 tail = substr (OID.end()-3, OID.end());
285 }
286}
287
288static void recurse_contents (ResultDocInfo_t section, const bool &is_classify,
289 const text_t &collection, const text_tset &metadata,
290 recptproto *collectproto, FilterResponse_t &response,
291 ostream &logout) {
292
293 int haschildren = section.metadata["haschildren"].values[0].getint();
294 const text_t &doctype = section.metadata["doctype"].values[0];
295
296 if ((haschildren == 1) && ((!is_classify) || (doctype == "classify"))) {
297 FilterResponse_t tmp;
298 bool getParents = false;
299 get_children (section.OID, collection, metadata, getParents, collectproto, tmp, logout);
300 ResultDocInfo_tarray::iterator thisdoc = tmp.docInfo.begin();
301 ResultDocInfo_tarray::iterator lastdoc = tmp.docInfo.end();
302 while (thisdoc != lastdoc) {
303 response.docInfo.push_back (*thisdoc);
304 recurse_contents (*thisdoc, is_classify, collection, metadata,
305 collectproto, response, logout);
306 thisdoc ++;
307 }
308 }
309}
310
311// get_contents returns OIDs and metadata of all contents
312// below (and including) OID.
313void get_contents (const text_t &topOID, const bool &is_classify,
314 text_tset &metadata, const text_t &collection,
315 recptproto *collectproto, FilterResponse_t &response,
316 ostream &logout) {
317
318 if (topOID.empty()) return;
319 response.clear();
320
321 metadata.insert ("haschildren");
322 metadata.insert ("doctype");
323
324 // get topOIDs info
325 if (get_info (topOID, collection, metadata, false, collectproto, response, logout))
326 recurse_contents (response.docInfo[0], is_classify, collection,
327 metadata, collectproto, response, logout);
328}
329
330// is_child_of returns true if OID2 is a child of OID1
331bool is_child_of(const text_t &OID1, const text_t &OID2) {
332
333 text_t parent = get_parent(OID2);
334
335 while (!parent.empty()) {
336 if (parent == OID1) return true;
337 parent = get_parent(parent);
338 }
339 return false;
340}
Note: See TracBrowser for help on using the repository browser.