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

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

Fixed some inconsistencies in the resumption tokens used in the ListSets service, and removed the collection build date because this request is not collection-specific.

  • Property svn:keywords set to Author Date Id Revision
File size: 7.3 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 output << " <setName>" << collection << "</setName>" << endl;
189 output << " </set>" << endl;
190 this->setsOutput++;
191 }
192
193 // Now loop through displaying the next matching records
194 while (set_iterator != sets_response.docInfo.end())
195 {
196 text_t set = (*set_iterator).OID;
197
198 // Only classifiers with supportsmemberof become OAI sets, for reasons I don't really understand
199 text_tset set_metadata;
200 set_metadata.insert("supportsmemberof");
201 set_metadata.insert("Title");
202 FilterResponse_t set_response;
203 get_info(set, collection, "", set_metadata, false, protocol, set_response, *this->logout);
204
205 if (set_response.docInfo[0].metadata["supportsmemberof"].values.size() > 0 && set_response.docInfo[0].metadata["supportsmemberof"].values[0] == "true")
206 {
207 // If we've output the desired number of records return a resumptionToken and we're done
208 if (this->setsOutput == this->configuration->resumeAfter())
209 {
210 ResumptionToken resumption_token("", "", "", "", "", collection + ":" + set);
211
212 // Don't add any whitespace around the resumption token as it can confuse harvesters/validators
213 output << " <resumptionToken>" << resumption_token.getResumptionTokenString() << "</resumptionToken>" << endl;
214 return false;
215 }
216
217 // Otherwise output this set and increment the count
218 text_t set_title = set_response.docInfo[0].metadata["Title"].values[0];
219 output << " <set>" << endl;
220 output << " <setSpec>" << collection << ":" << set << "</setSpec>" << endl;
221 output << " <setName>" << collection << ":" << set_title << "</setName>" << endl;
222 output << " </set>" << endl;
223 this->setsOutput++;
224 }
225
226 set_iterator++;
227 }
228
229 return true;
230}
Note: See TracBrowser for help on using the repository browser.