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

Last change on this file since 11259 was 11259, checked in by mdewsnip, 18 years ago

Various little bug fixes and improvements (many to get things working with Visual Studio 2005), by Emanuel Dejanu.

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