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

Last change on this file since 13116 was 13116, checked in by kjdon, 18 years ago

added .rt to the list of OID modifiers - this is the root id of the document

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 10.3 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);
[7414]68 ++here;
[211]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
[7414]77bool get_info (const text_t &OID, const text_t &collection, const text_t &lang,
[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
[2261]84 comerror_t err = noError;
[248]85 FilterRequest_t request;
[1443]86 request.clear();
[248]87
88 request.filterName = "NullFilter";
[7414]89 request.filterLang = lang;
[248]90 request.filterResultOptions = FRmetadata;
[278]91 request.getParents = getParents;
[248]92 request.fields = metadata;
[472]93 request.docSet.push_back (OID);
[1695]94 assert (collectproto != NULL);
[1860]95
[248]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 }
[505]105
[248]106 return true;
[211]107}
108
[1347]109// overloaded, to allow "custom" filter options.
[7414]110bool get_info (const text_t &OID, const text_t &collection, const text_t &lang,
[1347]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
[2261]118 comerror_t err = noError;
[1347]119 FilterRequest_t request;
120
121 request.filterName = "NullFilter";
[7414]122 request.filterLang = lang;
[1347]123 request.filterResultOptions = FRmetadata;
124 request.getParents = getParents;
125 request.filterOptions = options;
126 request.fields = metadata;
127 request.docSet.push_back (OID);
[1695]128
129 assert (collectproto != NULL);
[1347]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
[7414]143bool get_info (const text_tarray &OIDs, const text_t &collection, const text_t &lang,
[649]144 const text_tset &metadata, bool getParents,
[472]145 recptproto *collectproto, FilterResponse_t &response,
[423]146 ostream &logout) {
147
148 response.clear();
149 if (OIDs.empty()) return true;
150
[2261]151 comerror_t err = noError;
[423]152 FilterRequest_t request;
153
154 request.filterName = "NullFilter";
[7414]155 request.filterLang = lang;
[423]156 request.filterResultOptions = FRmetadata;
157 request.getParents = getParents;
158 request.fields = metadata;
159
[472]160 request.docSet = OIDs;
[423]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 }
[505]170
[423]171 return true;
172}
173
[1347]174
175
[257]176// has_children returns true if OID has children
[7414]177bool has_children (const text_t &OID, const text_t &collection, const text_t &lang,
[257]178 recptproto *collectproto, ostream &logout) {
179
180 FilterResponse_t response;
[649]181 text_tset metadata;
182 metadata.insert ("haschildren");
[257]183
[7414]184 if (get_info (OID, collection, lang, metadata, false, collectproto, response, logout)) {
[649]185 if (response.docInfo[0].metadata["haschildren"].values[0] == "1")
[257]186 return true;
187 }
188 return false;
189}
190
191
[248]192// get_children does a protocol call and returns (in response) the OIDs and
[649]193// metadata of all the children of OID. The metadata set should be loaded
[248]194// with whatever metadata fields are to be requested.
[211]195
[7414]196bool get_children (const text_t &OID, const text_t &collection, const text_t &lang,
[649]197 const text_tset &metadata, bool getParents,
[406]198 recptproto *collectproto, FilterResponse_t &response,
199 ostream &logout) {
[248]200
201 response.clear();
202
[2261]203 comerror_t err = noError;
[248]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";
[7414]211 request.filterLang = lang;
[248]212 request.filterResultOptions = FROID | FRmetadata;
213 request.fields = metadata;
[406]214 request.getParents = getParents;
[248]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
[211]229// get_parent returns the parent of the document or classification
230// specified by OID
[11259]231text_t get_parent (const text_t& OID)
232{
233 if (OID.empty() || is_top (OID)) return g_EmptyText;
[211]234
235 text_t::const_iterator begin = OID.begin();
236 text_t::const_iterator here = (OID.end() - 1);
237
238 while (here >= begin) {
[11259]239 if (*here == '.')
240 break;
241 if (here == begin)
242 break;
[9620]243 --here;
[211]244 }
[11259]245
246 if (here != begin) {
247 text_t parentOID;
248 parentOID.appendrange(begin, here);
249 return parentOID;
250 }
251
252 return g_EmptyText;
[211]253}
254
[257]255// takes an OID like ".2 and replaces the " with parent
[248]256void translate_parent (text_t &OID, const text_t &parent) {
[211]257
[248]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);
[7414]265 ++here;
[248]266 }
267 OID = temp;
[211]268}
[248]269
270// shrink_parent does the opposite to translate_parent
271void shrink_parent (text_t &OID) {
272
[257]273 text_tarray tmp;
274 splitchar (OID.begin(), OID.end(), '.', tmp);
275 OID = "\"." + tmp.back();
[248]276}
277
[13116]278// checks if OID uses ".fc", ".lc", ".pr", "rt", ".ns",
279// or ".ps" syntax (first child, last child, parent, root,
[248]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" ||
[13116]287 tail == ".rt" || tail == ".ns" || tail == ".ps") return true;
[248]288
289 return false;
290}
[257]291
[280]292// strips the ".fc", ".lc", ".pr", ".ns",
293// or ".ps" suffix from the end of OID
294void strip_suffix (text_t &OID) {
[257]295
[280]296 text_t tail = substr (OID.end()-3, OID.end());
297 while (tail == ".fc" || tail == ".lc" || tail == ".pr" ||
[13116]298 tail == ".rt" || tail == ".ns" || tail == ".ps") {
[280]299 OID.erase (OID.end()-3, OID.end());
300 tail = substr (OID.end()-3, OID.end());
301 }
302}
303
[649]304static void recurse_contents (ResultDocInfo_t section, const bool &is_classify,
[7414]305 const text_t &collection, const text_t &lang,
306 const text_tset &metadata,
[649]307 recptproto *collectproto, FilterResponse_t &response,
308 ostream &logout) {
[445]309
[649]310 int haschildren = section.metadata["haschildren"].values[0].getint();
311 const text_t &doctype = section.metadata["doctype"].values[0];
[257]312
[649]313 if ((haschildren == 1) && ((!is_classify) || (doctype == "classify"))) {
[257]314 FilterResponse_t tmp;
[406]315 bool getParents = false;
[7414]316 get_children (section.OID, collection, lang, metadata, getParents, collectproto, tmp, logout);
[649]317 ResultDocInfo_tarray::iterator thisdoc = tmp.docInfo.begin();
318 ResultDocInfo_tarray::iterator lastdoc = tmp.docInfo.end();
[257]319 while (thisdoc != lastdoc) {
320 response.docInfo.push_back (*thisdoc);
[7414]321 recurse_contents (*thisdoc, is_classify, collection, lang, metadata,
[649]322 collectproto, response, logout);
[7414]323 ++thisdoc;
[257]324 }
325 }
326}
327
328// get_contents returns OIDs and metadata of all contents
329// below (and including) OID.
[649]330void get_contents (const text_t &topOID, const bool &is_classify,
[7414]331 text_tset &metadata, const text_t &collection, const text_t &lang,
[649]332 recptproto *collectproto, FilterResponse_t &response,
333 ostream &logout) {
[257]334
[445]335 if (topOID.empty()) return;
[257]336 response.clear();
337
[649]338 metadata.insert ("haschildren");
339 metadata.insert ("doctype");
[445]340
[257]341 // get topOIDs info
[7414]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 }
[257]346}
[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.