source: gsdl/trunk/runtime-src/src/oaiservr/listsetsaction.cpp@ 20629

Last change on this file since 20629 was 20629, checked in by mdewsnip, 15 years ago

Added new "oaisetname" and "oaisetdescription" configuration options in the oai.cfg file, for setting the setName and setDescription values in the ListSets response.

  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 KB
Line 
1#include "listsetsaction.h"
2
3#include "resumptiontoken.h"
4#include "recptprototools.h"
5#include "oaitools.h"
6
7
8bool listsetsaction::validateAction(recptproto *protocol, oaiargs &params)
9{
10 // ----------------------------------------------------------------------------
11 // 1. Check for invalid arguments
12 // ----------------------------------------------------------------------------
13 bool invalid_argument_supplied = false;
14 text_tmap::const_iterator param_iterator = params.begin();
15 while (param_iterator != params.end())
16 {
17 // Check for arguments that aren't valid for this action
18 if (param_iterator->first != "verb" &&
19 param_iterator->first != "resumptionToken")
20 {
21 // We've found an invalid argument
22 invalid_argument_supplied = true;
23
24 // Delete the invalid argument from the list so it doesn't end up in the <request> tag that is returned
25 params.erase(param_iterator->first);
26 }
27
28 param_iterator++;
29 }
30
31 // If we found an invalid argument it's an error, so don't go any further
32 if (invalid_argument_supplied)
33 {
34 this->errorType = "badArgument";
35 return false;
36 }
37
38 // ----------------------------------------------------------------------------
39 // 2. Handle any exclusive arguments
40 // ----------------------------------------------------------------------------
41
42 // The resumptionToken argument is exclusive
43 if (params["resumptionToken"] != "")
44 {
45 // This argument is exclusive, so no other arguments are allowed (except "verb" of course)
46 if (params.getSize() != 2)
47 {
48 this->errorType = "badArgument";
49 return false;
50 }
51
52 // Check the resumption token is valid
53 ResumptionToken token(params["resumptionToken"]);
54 if (token.isValid())
55 {
56 // Everything is fine, and we don't continue further because this is an exclusive argument
57 this->errorType = "";
58 return true;
59 }
60 else
61 {
62 // There was an error with the resumption token
63 this->errorType = "badResumptionToken";
64 return false;
65 }
66 }
67
68 // ----------------------------------------------------------------------------
69 // 3. Handle any required arguments
70 // ----------------------------------------------------------------------------
71
72 // None!
73
74 // ----------------------------------------------------------------------------
75 // 4. Check any remaining arguments
76 // ----------------------------------------------------------------------------
77
78 // None!
79
80 // If we've reached here everything must be fine
81 this->errorType = "";
82 return true;
83}
84
85
86bool listsetsaction::output_content(ostream &output, recptproto *protocol, oaiargs &params)
87{
88 // Reset variables
89 this->setsOutput = 0;
90
91 text_t position = "";
92
93 // Process the resumptionToken if there is one
94 if (params["resumptionToken"] != "")
95 {
96 ResumptionToken resumption_token(params["resumptionToken"]);
97 position = resumption_token.getPosition();
98 }
99
100 // Get a list of the collections available
101 text_tarray& collections = this->configuration->getCollectionsList();
102 if (collections.size() == 0)
103 {
104 return false;
105 }
106
107 // Get the current collection from the position value
108 text_t collection_name = "";
109 oaiclassifier::toGSDL(collection_name, position);
110
111 // Find the starting collection
112 text_tarray::iterator collection_iterator = collections.begin();
113 while (collection_iterator != collections.end())
114 {
115 if (collection_name == "" || collection_name == *collection_iterator)
116 {
117 break;
118 }
119
120 collection_iterator++;
121 }
122
123 // Now loop through the remaining collections
124 while (collection_iterator != collections.end())
125 {
126 collection_name = (*collection_iterator);
127
128 // If we've output the desired number of records return a resumptionToken and we're done
129 if (this->setsOutput == this->configuration->resumeAfter())
130 {
131 ResumptionToken resumption_token("", "", "", "", "", collection_name);
132
133 // Don't add any whitespace around the resumption token as it can confuse harvesters/validators
134 output << " <resumptionToken>" << resumption_token.getResumptionTokenString() << "</resumptionToken>" << endl;
135 return true;
136 }
137
138 // If output_content_for_col() returns false a resumption token has been output, so it's time to stop
139 if (output_content_for_col(output, protocol, params, collection_name) == false)
140 {
141 return true;
142 }
143
144 collection_iterator++;
145 }
146
147 return true;
148}
149
150
151bool listsetsaction::output_content_for_col(ostream &output, recptproto *protocol, oaiargs &params, text_t collection)
152{
153 text_t position = "";
154
155 // Process the resumptionToken if there is one
156 if (params["resumptionToken"] != "")
157 {
158 ResumptionToken resumption_token(params["resumptionToken"]);
159 position = resumption_token.getPosition();
160 }
161
162 // Get the list of sets in this collection
163 // Collections should not contain too many sets otherwise this will use a lot of time and memory
164 text_tset metadata; // Must be empty for efficiency
165 FilterResponse_t sets_response;
166 get_children("browse", collection, "", metadata, false, protocol, sets_response, *this->logout);
167
168 // Find the starting position, if necessary
169 ResultDocInfo_tarray::iterator set_iterator = sets_response.docInfo.begin();
170 if (this->setsOutput == 0)
171 {
172 while (set_iterator != sets_response.docInfo.end())
173 {
174 if (position == "" || position == (collection + ":" + (*set_iterator).OID))
175 {
176 break;
177 }
178
179 set_iterator++;
180 }
181 }
182
183 // Output the collection as a set
184 if (position == "" || position == collection)
185 {
186 output << " <set>" << endl;
187 output << " <setSpec>" << collection << "</setSpec>" << endl;
188 if (this->configuration->getSetName(collection) != "")
189 {
190 output << " <setName>" << this->configuration->getSetName(collection) << "</setName>" << endl;
191 }
192 else
193 {
194 output << " <setName>" << collection << "</setName>" << endl;
195 }
196 if (this->configuration->getSetDescription(collection) != "")
197 {
198 output << " <setDescription>" << this->configuration->getSetDescription(collection) << "</setDescription>" << endl;
199 }
200 output << " </set>" << endl;
201 this->setsOutput++;
202 }
203
204 // Now loop through displaying the next matching records
205 while (set_iterator != sets_response.docInfo.end())
206 {
207 text_t set = (*set_iterator).OID;
208
209 // Only classifiers with supportsmemberof become OAI sets, for reasons I don't really understand
210 text_tset set_metadata;
211 set_metadata.insert("supportsmemberof");
212 set_metadata.insert("Title");
213 FilterResponse_t set_response;
214 get_info(set, collection, "", set_metadata, false, protocol, set_response, *this->logout);
215
216 if (set_response.docInfo[0].metadata["supportsmemberof"].values.size() > 0 && set_response.docInfo[0].metadata["supportsmemberof"].values[0] == "true")
217 {
218 // If we've output the desired number of records return a resumptionToken and we're done
219 if (this->setsOutput == this->configuration->resumeAfter())
220 {
221 ResumptionToken resumption_token("", "", "", "", "", collection + ":" + set);
222
223 // Don't add any whitespace around the resumption token as it can confuse harvesters/validators
224 output << " <resumptionToken>" << resumption_token.getResumptionTokenString() << "</resumptionToken>" << endl;
225 return false;
226 }
227
228 // Otherwise output this set and increment the count
229 output << " <set>" << endl;
230 output << " <setSpec>" << collection << ":" << set << "</setSpec>" << endl;
231 if (this->configuration->getSetName(collection + ":" + set) != "")
232 {
233 output << " <setName>" << this->configuration->getSetName(collection + ":" + set) << "</setName>" << endl;
234 }
235 else
236 {
237 output << " <setName>" << set_response.docInfo[0].metadata["Title"].values[0] << "</setName>" << endl;
238 }
239 if (this->configuration->getSetDescription(collection + ":" + set) != "")
240 {
241 output << " <setDescription>" << this->configuration->getSetDescription(collection + ":" + set) << "</setDescription>" << endl;
242 }
243 output << " </set>" << endl;
244 this->setsOutput++;
245 }
246
247 set_iterator++;
248 }
249
250 return true;
251}
Note: See TracBrowser for help on using the repository browser.