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

Last change on this file since 533 was 533, 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: 11.5 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 * $Id: OIDtools.cpp 533 1999-09-07 04:57:01Z sjboddie $
25 *
26 *********************************************************************/
27
28/*
29 $Log$
30 Revision 1.16 1999/09/07 04:56:51 sjboddie
31 added GPL notice
32
33 Revision 1.15 1999/09/02 00:22:04 rjmcnab
34 added extra check in get_info
35
36 Revision 1.14 1999/08/25 04:45:25 sjboddie
37 changed FilterRequest_t::docSet into an array
38
39 Revision 1.13 1999/08/10 22:44:06 sjboddie
40 altered the get_contents function so it's now passed metadata
41 rather than having it hard-coded
42
43 Revision 1.12 1999/07/30 02:26:44 sjboddie
44 added overloaded get_info function for getting info on multiple OIDs
45
46 Revision 1.11 1999/07/20 02:59:03 sjboddie
47 get_children now takes a getParents argument
48
49 Revision 1.10 1999/07/07 05:47:41 sjboddie
50 changed around the way browsetools works
51
52 Revision 1.9 1999/06/16 23:51:53 sjboddie
53 added a strip_suffix function
54
55 Revision 1.8 1999/06/16 03:11:25 sjboddie
56 get_info() now takes a getParents argument
57
58 Revision 1.7 1999/06/16 02:05:23 sjboddie
59 just changed a comment that was confusing me
60
61 Revision 1.6 1999/05/10 03:40:25 sjboddie
62 lots of changes - slowly getting document action sorted out
63
64 Revision 1.5 1999/04/30 01:59:37 sjboddie
65 lots of stuff - getting documentaction working (documentaction replaces
66 old browseaction)
67
68 Revision 1.4 1999/03/29 02:14:25 sjboddie
69
70 More changes to browseaction
71
72 Revision 1.3 1999/03/25 03:13:42 sjboddie
73
74 More library functions for dealing with OIDs. Many of them just
75 return dummy data at present
76
77 Revision 1.2 1999/03/05 03:53:53 sjboddie
78
79 fixed some bugs
80
81 Revision 1.1 1999/03/04 22:38:20 sjboddie
82
83 Added subjectbrowseaction. - Doesn't do anything yet.
84
85 */
86
87#include "OIDtools.h"
88
89
90// returns (in top) the top level of OID (i.e. everything
91// up until the first dot)
92void get_top (const text_t &OID, text_t &top) {
93
94 top.clear();
95 if (OID.empty()) return;
96
97 text_t::const_iterator begin = OID.begin();
98 text_t::const_iterator end = OID.end();
99
100 top.appendrange (begin, findchar(begin, end, '.'));
101}
102
103
104// checks if OID is top level (i.e. contains no dots)
105bool is_top (const text_t &OID) {
106
107 if (OID.empty()) return true;
108
109 text_t::const_iterator here = OID.begin();
110 text_t::const_iterator end = OID.end();
111 here = findchar (here, end, '.');
112
113 if (here == end) return true;
114 return false;
115}
116
117
118// get_parents_array loads the parents array with all the parents of the
119// document or classification specified by OID (not including OID itself)
120void get_parents_array (const text_t &OID, text_tarray &parents) {
121
122 parents.erase (parents.begin(), parents.end());
123
124 text_t::const_iterator here = OID.begin ();
125 text_t::const_iterator end = OID.end ();
126 text_t thisparent;
127
128 while (here != end) {
129 if (*here == '.') parents.push_back(thisparent);
130 thisparent.push_back(*here);
131 here ++;
132 }
133}
134
135
136// get_info does a protocol call and returns (in response) the metadata
137// associated with OID. The metadata array should be loaded with whatever
138// metadata fields are to be requested.
139
140bool get_info (const text_t &OID, const text_t &collection,
141 const text_tarray &metadata, bool getParents,
142 recptproto *collectproto, FilterResponse_t &response,
143 ostream &logout) {
144
145 response.clear();
146
147 comerror_t err;
148 FilterRequest_t request;
149
150 request.filterName = "NullFilter";
151 request.filterResultOptions = FRmetadata;
152 request.getParents = getParents;
153 request.fields = metadata;
154 request.docSet.push_back (OID);
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 for " << OID
161 << " in OIDtools::get_info ("
162 << get_comerror_string (err) << ")\n";
163 return false;
164 }
165
166 // check the result to make sure we have the right amount of metadata
167 if (!response.docInfo.empty() &&
168 response.docInfo[0].metadata.size() != metadata.size()) return false;
169
170 return true;
171}
172
173bool get_info (const text_tarray &OIDs, const text_t &collection,
174 const text_tarray &metadata, bool getParents,
175 recptproto *collectproto, FilterResponse_t &response,
176 ostream &logout) {
177
178 response.clear();
179 if (OIDs.empty()) return true;
180
181 comerror_t err;
182 FilterRequest_t request;
183
184 request.filterName = "NullFilter";
185 request.filterResultOptions = FRmetadata;
186 request.getParents = getParents;
187 request.fields = metadata;
188
189 request.docSet = OIDs;
190
191 collectproto->filter (collection, request, response, err, logout);
192 if (err != noError) {
193 outconvertclass text_t2ascii;
194 logout << text_t2ascii
195 << "Error: call to filter failed in OIDtools::get_info ("
196 << get_comerror_string (err) << ")\n";
197 return false;
198 }
199
200 // check the result to make sure we have the right amount of metadata
201 if (!response.docInfo.empty() &&
202 response.docInfo[0].metadata.size() != metadata.size()) return false;
203
204 return true;
205}
206
207// has_children returns true if OID has children
208bool has_children (const text_t &OID, const text_t &collection,
209 recptproto *collectproto, ostream &logout) {
210
211 FilterResponse_t response;
212 text_tarray metadata;
213 metadata.push_back ("haschildren");
214
215 if (get_info (OID, collection, metadata, false, collectproto, response, logout)) {
216 if (response.docInfo[0].metadata[0].values[0] == "1")
217 return true;
218 }
219 return false;
220}
221
222
223// get_children does a protocol call and returns (in response) the OIDs and
224// metadata of all the children of OID. The metadata array should be loaded
225// with whatever metadata fields are to be requested.
226
227bool get_children (const text_t &OID, const text_t &collection,
228 const text_tarray &metadata, bool getParents,
229 recptproto *collectproto, FilterResponse_t &response,
230 ostream &logout) {
231
232 response.clear();
233
234 comerror_t err;
235 FilterRequest_t request;
236 OptionValue_t option;
237
238 option.name = "ParentNode";
239 option.value = OID;
240 request.filterOptions.push_back (option);
241 request.filterName = "BrowseFilter";
242 request.filterResultOptions = FROID | FRmetadata;
243 request.fields = metadata;
244 request.getParents = getParents;
245
246 collectproto->filter (collection, request, response, err, logout);
247
248 if (err != noError) {
249 outconvertclass text_t2ascii;
250 logout << text_t2ascii
251 << "Error: call to filter failed for " << OID
252 << " in OIDtools::get_children ("
253 << get_comerror_string (err) << ")\n";
254 return false;
255 }
256 return true;
257}
258
259// get_parent returns the parent of the document or classification
260// specified by OID
261text_t get_parent (text_t OID) {
262
263 if (OID.empty() || is_top (OID)) return "";
264
265 text_t::const_iterator begin = OID.begin();
266 text_t::const_iterator here = (OID.end() - 1);
267
268 while (here >= begin) {
269 OID.pop_back();
270 if (*here == '.') break;
271 here --;
272 }
273 return OID;
274}
275
276// takes an OID like ".2 and replaces the " with parent
277void translate_parent (text_t &OID, const text_t &parent) {
278
279 text_t::const_iterator here = OID.begin();
280 text_t::const_iterator end = OID.end();
281 text_t temp;
282
283 while (here != end) {
284 if (*here == '"') temp += parent;
285 else temp.push_back (*here);
286 here ++;
287 }
288 OID = temp;
289}
290
291// shrink_parent does the opposite to translate_parent
292void shrink_parent (text_t &OID) {
293
294 text_tarray tmp;
295 splitchar (OID.begin(), OID.end(), '.', tmp);
296 OID = "\"." + tmp.back();
297}
298
299// checks if OID uses ".fc", ".lc", ".pr", ".ns",
300// or ".ps" syntax (first child, last child, parent,
301// next sibling, previous sibling)
302bool needs_translating (const text_t &OID) {
303
304 if (OID.size() < 4) return false;
305
306 text_t tail = substr (OID.end()-3, OID.end());
307 if (tail == ".fc" || tail == ".lc" || tail == ".pr" ||
308 tail == ".ns" || tail == ".ps") return true;
309
310 return false;
311}
312
313// strips the ".fc", ".lc", ".pr", ".ns",
314// or ".ps" suffix from the end of OID
315void strip_suffix (text_t &OID) {
316
317 text_t tail = substr (OID.end()-3, OID.end());
318 while (tail == ".fc" || tail == ".lc" || tail == ".pr" ||
319 tail == ".ns" || tail == ".ps") {
320 OID.erase (OID.end()-3, OID.end());
321 tail = substr (OID.end()-3, OID.end());
322 }
323}
324
325void recurse_contents (const ResultDocInfo_t section, const bool &classify,
326 int &totalcols, const text_t &collection,
327 const text_tarray &metadata, recptproto *collectproto,
328 FilterResponse_t &response, ostream &logout) {
329
330 int metasize = section.metadata.size();
331
332 int haschildren = section.metadata[metasize-2].values[0].getint();
333 const text_t &doctype = section.metadata[metasize-1].values[0];
334 int cols;
335
336 if ((haschildren == 1) && ((!classify) || (doctype == "classify"))) {
337 text_t parent = response.docInfo.back().OID;
338 int parentcols = countchar (parent.begin(), parent.end(), '.');
339 FilterResponse_t tmp;
340 bool getParents = false;
341 get_children (section.OID, collection, metadata, getParents, collectproto, tmp, logout);
342 ResultDocInfo_tarray::const_iterator thisdoc = tmp.docInfo.begin();
343 ResultDocInfo_tarray::const_iterator lastdoc = tmp.docInfo.end();
344 while (thisdoc != lastdoc) {
345 if (((*thisdoc).metadata[metasize-1].values[0] != "classify") && (classify))
346 cols = parentcols + 1;
347 else
348 cols = countchar ((*thisdoc).OID.begin(), (*thisdoc).OID.end(), '.');
349 if (cols > totalcols) totalcols = cols;
350 response.docInfo.push_back (*thisdoc);
351 recurse_contents (*thisdoc, classify, totalcols, collection,
352 metadata, collectproto, response, logout);
353 thisdoc ++;
354 }
355 }
356}
357
358// get_contents returns OIDs and metadata of all contents
359// below (and including) OID.
360void get_contents (const text_t &topOID, const text_t &classifytype,
361 text_tarray &metadata, int &totalcols,
362 const text_t &collection, recptproto *collectproto,
363 FilterResponse_t &response, ostream &logout) {
364
365 if (topOID.empty()) return;
366 bool classify = false;
367 response.clear();
368
369 metadata.push_back("haschildren");
370 metadata.push_back("doctype");
371
372 // we don't want to recurse all the way down through each document
373 // if we're expanding top level contents
374 if (classifytype == "classify") classify = true;
375
376 // update totalcols
377 totalcols = countchar (topOID.begin(), topOID.end(), '.');
378
379 // get topOIDs info
380 if (get_info (topOID, collection, metadata, false, collectproto, response, logout))
381 recurse_contents (response.docInfo[0], classify, totalcols, collection,
382 metadata, collectproto, response, logout);
383}
384
385// is_child_of returns true if OID2 is a child of OID1
386bool is_child_of(const text_t &OID1, const text_t &OID2) {
387
388 text_t parent = get_parent(OID2);
389
390 while (!parent.empty()) {
391 if (parent == OID1) return true;
392 parent = get_parent(parent);
393 }
394 return false;
395}
Note: See TracBrowser for help on using the repository browser.