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

Last change on this file since 1443 was 1443, checked in by davidb, 24 years ago

Changes to support nested {If} and {Or} statements in macro files.
Also expansion of metadata if it includes further metadata. The two
can be intermixed -- metadata can include metadata that has {If}
and {Or} statements.

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