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

Last change on this file since 1804 was 1695, checked in by nzdl, 24 years ago

Fixed a bug in the cross-collection searching stuff

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