source: main/trunk/greenstone2/runtime-src/src/oaiservr/listsetsaction.cpp@ 27528

Last change on this file since 27528 was 27528, checked in by kjdon, 11 years ago

implemented oaisupercollection. add to oai.cfg and the server will make a new set containing the specified collections

  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/**********************************************************************
2 *
3 * listsetsaction.cpp --
4 *
5 * Copyright (C) 2004-2010 The New Zealand Digital Library Project
6 *
7 * A component of the Greenstone digital library software
8 * from the New Zealand Digital Library Project at the
9 * University of Waikato, New Zealand.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 *********************************************************************/
26
27#include "listsetsaction.h"
28
29#include "resumptiontoken.h"
30#include "recptprototools.h"
31#include "oaitools.h"
32
33
34bool listsetsaction::validateAction(recptproto *protocol, oaiargs &params)
35{
36 // ----------------------------------------------------------------------------
37 // 1. Check for invalid arguments
38 // ----------------------------------------------------------------------------
39 bool invalid_argument_supplied = false;
40 text_tmap::const_iterator param_iterator = params.begin();
41 while (param_iterator != params.end())
42 {
43 // Check for arguments that aren't valid for this action
44 if (param_iterator->first != "verb" &&
45 param_iterator->first != "resumptionToken")
46 {
47 // We've found an invalid argument
48 invalid_argument_supplied = true;
49
50 // Delete the invalid argument from the list so it doesn't end up in the <request> tag that is returned
51 params.erase(param_iterator->first);
52 }
53
54 param_iterator++;
55 }
56
57 // If we found an invalid argument it's an error, so don't go any further
58 if (invalid_argument_supplied)
59 {
60 this->errorType = "badArgument";
61 return false;
62 }
63
64 // ----------------------------------------------------------------------------
65 // 2. Handle any exclusive arguments
66 // ----------------------------------------------------------------------------
67
68 // The resumptionToken argument is exclusive
69 if (params["resumptionToken"] != "")
70 {
71 // This argument is exclusive, so no other arguments are allowed (except "verb" of course)
72 if (params.getSize() != 2)
73 {
74 this->errorType = "badArgument";
75 return false;
76 }
77
78 // Check the resumption token is valid
79 ResumptionToken token(params["resumptionToken"]);
80 if (token.isValid())
81 {
82 // Everything is fine, and we don't continue further because this is an exclusive argument
83 this->errorType = "";
84 return true;
85 }
86 else
87 {
88 // There was an error with the resumption token
89 this->errorType = "badResumptionToken";
90 return false;
91 }
92 }
93
94 // ----------------------------------------------------------------------------
95 // 3. Handle any required arguments
96 // ----------------------------------------------------------------------------
97
98 // None!
99
100 // ----------------------------------------------------------------------------
101 // 4. Check any remaining arguments
102 // ----------------------------------------------------------------------------
103
104 // None!
105
106 // If we've reached here everything must be fine
107 this->errorType = "";
108 return true;
109}
110
111
112bool listsetsaction::output_content(ostream &output, recptproto *protocol, oaiargs &params)
113{
114 // Reset variables
115 this->setsOutput = 0;
116
117 text_t position = "";
118
119 // Process the resumptionToken if there is one
120 if (params["resumptionToken"] != "")
121 {
122 ResumptionToken resumption_token(params["resumptionToken"]);
123 position = resumption_token.getPosition();
124 }
125
126 // Get a list of the collections available
127 text_tarray& collections = this->configuration->getCollectionsList();
128 if (collections.size() == 0)
129 {
130 return false;
131 }
132
133 // if no resumption token, output the super colls. Otherwise, start from
134 // the collection list correct position.
135 // Assume for now that super coll list is always in the first list
136 text_t set_name ="";
137 if (position == "") {
138 text_tarray& supercolls = this->configuration->getSuperCollectionsList();
139 if (collections.size() != 0) {
140 text_tarray::iterator supercoll_iterator = supercolls.begin();
141 while (supercoll_iterator != supercolls.end()) {
142 set_name = (*supercoll_iterator);
143 output_content_for_supercol(output, set_name);
144 supercoll_iterator++;
145 }
146 }
147 }
148 // Get the current collection from the position value
149 text_t collection_name = "";
150 oaiclassifier::toGSDL(collection_name, position);
151
152 // Find the starting collection
153 text_tarray::iterator collection_iterator = collections.begin();
154 while (collection_iterator != collections.end())
155 {
156 if (collection_name == "" || collection_name == *collection_iterator)
157 {
158 break;
159 }
160
161 collection_iterator++;
162 }
163
164 // Now loop through the remaining collections
165 while (collection_iterator != collections.end())
166 {
167 collection_name = (*collection_iterator);
168
169 // If we've output the desired number of records return a resumptionToken and we're done
170 if (this->setsOutput == this->configuration->resumeAfter())
171 {
172 ResumptionToken resumption_token("", "", "", "", "", collection_name);
173
174 // Don't add any whitespace around the resumption token as it can confuse harvesters/validators
175 output << " <resumptionToken>" << resumption_token.getResumptionTokenString() << "</resumptionToken>" << endl;
176 return true;
177 }
178
179 // If output_content_for_col() returns false a resumption token has been output, so it's time to stop
180 if (output_content_for_col(output, protocol, params, collection_name) == false)
181 {
182 return true;
183 }
184
185 collection_iterator++;
186 }
187
188 return true;
189}
190
191bool listsetsaction::output_content_for_supercol(ostream &output, text_t supercoll) {
192 utf8outconvertclass utf8convert;
193 output << utf8convert << " <set>\n";
194 output << utf8convert << " <setSpec>" << supercoll << "</setSpec>\n";
195 if (this->configuration->getSetName(supercoll) != "")
196 {
197 output << utf8convert << " <setName>" << this->configuration->getSetName(supercoll) << "</setName>\n";
198 }
199 else
200 {
201 output << utf8convert << " <setName>" << supercoll << "</setName>\n";
202 }
203 if (this->configuration->getSetDescription(supercoll) != "")
204 {
205 output << utf8convert << " <setDescription>" << this->configuration->getSetDescription(supercoll) << "</setDescription>\n";
206 }
207 output << utf8convert << " </set>\n";
208 this->setsOutput++;
209}
210
211
212
213
214bool listsetsaction::output_content_for_col(ostream &output, recptproto *protocol, oaiargs &params, text_t collection)
215{
216 utf8outconvertclass utf8convert;
217 text_t position = "";
218
219 // Process the resumptionToken if there is one
220 if (params["resumptionToken"] != "")
221 {
222 ResumptionToken resumption_token(params["resumptionToken"]);
223 position = resumption_token.getPosition();
224 }
225
226 // Get the list of sets in this collection
227 // Collections should not contain too many sets otherwise this will use a lot of time and memory
228 text_tset metadata; // Must be empty for efficiency
229 FilterResponse_t sets_response;
230 get_children("browse", collection, "", metadata, false, protocol, sets_response, *this->logout);
231
232 // Find the starting position, if necessary
233 ResultDocInfo_tarray::iterator set_iterator = sets_response.docInfo.begin();
234 if (this->setsOutput == 0)
235 {
236 while (set_iterator != sets_response.docInfo.end())
237 {
238 if (position == "" || position == (collection + ":" + (*set_iterator).OID))
239 {
240 break;
241 }
242
243 set_iterator++;
244 }
245 }
246
247 // Output the collection as a set
248 if (position == "" || position == collection)
249 {
250 output << utf8convert << " <set>\n";
251 output << utf8convert << " <setSpec>" << collection << "</setSpec>\n";
252 if (this->configuration->getSetName(collection) != "")
253 {
254 output << utf8convert << " <setName>" << this->configuration->getSetName(collection) << "</setName>\n";
255 }
256 else
257 {
258 output << utf8convert << " <setName>" << collection << "</setName>\n";
259 }
260 if (this->configuration->getSetDescription(collection) != "")
261 {
262 output << utf8convert << " <setDescription>" << this->configuration->getSetDescription(collection) << "</setDescription>\n";
263 }
264 output << utf8convert << " </set>\n";
265 this->setsOutput++;
266 }
267
268 // Now loop through displaying the next matching records
269 while (set_iterator != sets_response.docInfo.end())
270 {
271 text_t set = (*set_iterator).OID;
272
273 // Only classifiers with supportsmemberof become OAI sets, for reasons I don't really understand
274 text_tset set_metadata;
275 set_metadata.insert("supportsmemberof");
276 set_metadata.insert("Title");
277 FilterResponse_t set_response;
278 get_info(set, collection, "", set_metadata, false, protocol, set_response, *this->logout);
279
280 if (set_response.docInfo[0].metadata["supportsmemberof"].values.size() > 0 && set_response.docInfo[0].metadata["supportsmemberof"].values[0] == "true")
281 {
282 // If we've output the desired number of records return a resumptionToken and we're done
283 if (this->setsOutput == this->configuration->resumeAfter())
284 {
285 ResumptionToken resumption_token("", "", "", "", "", collection + ":" + set);
286
287 // Don't add any whitespace around the resumption token as it can confuse harvesters/validators
288 output << " <resumptionToken>" << resumption_token.getResumptionTokenString() << "</resumptionToken>" << endl;
289 return false;
290 }
291
292 // Otherwise output this set and increment the count
293 output << utf8convert << " <set>\n";
294 output << utf8convert << " <setSpec>" << collection << ":" << set << "</setSpec>\n";
295 if (this->configuration->getSetName(collection + ":" + set) != "")
296 {
297 output << utf8convert << " <setName>" << this->configuration->getSetName(collection + ":" + set) << "</setName>\n";
298 }
299 else
300 {
301 output << utf8convert << " <setName>" << set_response.docInfo[0].metadata["Title"].values[0] << "</setName>\n";
302 }
303 if (this->configuration->getSetDescription(collection + ":" + set) != "")
304 {
305 output << utf8convert << " <setDescription>" << this->configuration->getSetDescription(collection + ":" + set) << "</setDescription>\n";
306 }
307 output << utf8convert << " </set>\n";
308 this->setsOutput++;
309 }
310
311 set_iterator++;
312 }
313
314 return true;
315}
Note: See TracBrowser for help on using the repository browser.