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

Last change on this file since 27220 was 22739, checked in by mdewsnip, 14 years ago

Added copyright header to runtime-src/src/oaiserver/*.cpp and runtime-src/src/oaiserver/*.h.

  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 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 // Get the current collection from the position value
134 text_t collection_name = "";
135 oaiclassifier::toGSDL(collection_name, position);
136
137 // Find the starting collection
138 text_tarray::iterator collection_iterator = collections.begin();
139 while (collection_iterator != collections.end())
140 {
141 if (collection_name == "" || collection_name == *collection_iterator)
142 {
143 break;
144 }
145
146 collection_iterator++;
147 }
148
149 // Now loop through the remaining collections
150 while (collection_iterator != collections.end())
151 {
152 collection_name = (*collection_iterator);
153
154 // If we've output the desired number of records return a resumptionToken and we're done
155 if (this->setsOutput == this->configuration->resumeAfter())
156 {
157 ResumptionToken resumption_token("", "", "", "", "", collection_name);
158
159 // Don't add any whitespace around the resumption token as it can confuse harvesters/validators
160 output << " <resumptionToken>" << resumption_token.getResumptionTokenString() << "</resumptionToken>" << endl;
161 return true;
162 }
163
164 // If output_content_for_col() returns false a resumption token has been output, so it's time to stop
165 if (output_content_for_col(output, protocol, params, collection_name) == false)
166 {
167 return true;
168 }
169
170 collection_iterator++;
171 }
172
173 return true;
174}
175
176
177bool listsetsaction::output_content_for_col(ostream &output, recptproto *protocol, oaiargs &params, text_t collection)
178{
179 utf8outconvertclass utf8convert;
180 text_t position = "";
181
182 // Process the resumptionToken if there is one
183 if (params["resumptionToken"] != "")
184 {
185 ResumptionToken resumption_token(params["resumptionToken"]);
186 position = resumption_token.getPosition();
187 }
188
189 // Get the list of sets in this collection
190 // Collections should not contain too many sets otherwise this will use a lot of time and memory
191 text_tset metadata; // Must be empty for efficiency
192 FilterResponse_t sets_response;
193 get_children("browse", collection, "", metadata, false, protocol, sets_response, *this->logout);
194
195 // Find the starting position, if necessary
196 ResultDocInfo_tarray::iterator set_iterator = sets_response.docInfo.begin();
197 if (this->setsOutput == 0)
198 {
199 while (set_iterator != sets_response.docInfo.end())
200 {
201 if (position == "" || position == (collection + ":" + (*set_iterator).OID))
202 {
203 break;
204 }
205
206 set_iterator++;
207 }
208 }
209
210 // Output the collection as a set
211 if (position == "" || position == collection)
212 {
213 output << utf8convert << " <set>\n";
214 output << utf8convert << " <setSpec>" << collection << "</setSpec>\n";
215 if (this->configuration->getSetName(collection) != "")
216 {
217 output << utf8convert << " <setName>" << this->configuration->getSetName(collection) << "</setName>\n";
218 }
219 else
220 {
221 output << utf8convert << " <setName>" << collection << "</setName>\n";
222 }
223 if (this->configuration->getSetDescription(collection) != "")
224 {
225 output << utf8convert << " <setDescription>" << this->configuration->getSetDescription(collection) << "</setDescription>\n";
226 }
227 output << utf8convert << " </set>\n";
228 this->setsOutput++;
229 }
230
231 // Now loop through displaying the next matching records
232 while (set_iterator != sets_response.docInfo.end())
233 {
234 text_t set = (*set_iterator).OID;
235
236 // Only classifiers with supportsmemberof become OAI sets, for reasons I don't really understand
237 text_tset set_metadata;
238 set_metadata.insert("supportsmemberof");
239 set_metadata.insert("Title");
240 FilterResponse_t set_response;
241 get_info(set, collection, "", set_metadata, false, protocol, set_response, *this->logout);
242
243 if (set_response.docInfo[0].metadata["supportsmemberof"].values.size() > 0 && set_response.docInfo[0].metadata["supportsmemberof"].values[0] == "true")
244 {
245 // If we've output the desired number of records return a resumptionToken and we're done
246 if (this->setsOutput == this->configuration->resumeAfter())
247 {
248 ResumptionToken resumption_token("", "", "", "", "", collection + ":" + set);
249
250 // Don't add any whitespace around the resumption token as it can confuse harvesters/validators
251 output << " <resumptionToken>" << resumption_token.getResumptionTokenString() << "</resumptionToken>" << endl;
252 return false;
253 }
254
255 // Otherwise output this set and increment the count
256 output << utf8convert << " <set>\n";
257 output << utf8convert << " <setSpec>" << collection << ":" << set << "</setSpec>\n";
258 if (this->configuration->getSetName(collection + ":" + set) != "")
259 {
260 output << utf8convert << " <setName>" << this->configuration->getSetName(collection + ":" + set) << "</setName>\n";
261 }
262 else
263 {
264 output << utf8convert << " <setName>" << set_response.docInfo[0].metadata["Title"].values[0] << "</setName>\n";
265 }
266 if (this->configuration->getSetDescription(collection + ":" + set) != "")
267 {
268 output << utf8convert << " <setDescription>" << this->configuration->getSetDescription(collection + ":" + set) << "</setDescription>\n";
269 }
270 output << utf8convert << " </set>\n";
271 this->setsOutput++;
272 }
273
274 set_iterator++;
275 }
276
277 return true;
278}
Note: See TracBrowser for help on using the repository browser.