root/gsdl/trunk/runtime-src/src/oaiservr/listsetsaction.cpp @ 20708

Revision 20708, 8.2 KB (checked in by mdewsnip, 10 years ago)

Same fix as made to identifyaction.cpp, to use a utf8outconvertclass when writing output so Unicode characters are correctly encoded as UTF-8.

  • Property svn:keywords set to Author Date Id Revision
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  utf8outconvertclass utf8convert;
154  text_t position = "";
155
156  // Process the resumptionToken if there is one
157  if (params["resumptionToken"] != "")
158  {
159    ResumptionToken resumption_token(params["resumptionToken"]);
160    position = resumption_token.getPosition();
161  }
162
163  // Get the list of sets in this collection
164  // Collections should not contain too many sets otherwise this will use a lot of time and memory
165  text_tset metadata;  // Must be empty for efficiency
166  FilterResponse_t sets_response;
167  get_children("browse", collection, "", metadata, false, protocol, sets_response, *this->logout);
168
169  // Find the starting position, if necessary
170  ResultDocInfo_tarray::iterator set_iterator = sets_response.docInfo.begin();
171  if (this->setsOutput == 0)
172  {
173    while (set_iterator != sets_response.docInfo.end())
174    {
175      if (position == "" || position == (collection + ":" + (*set_iterator).OID))
176      {
177    break;
178      }
179
180      set_iterator++;
181    }
182  }
183
184  // Output the collection as a set
185  if (position == "" || position == collection)
186  {
187    output << utf8convert << "  <set>\n";
188    output << utf8convert << "    <setSpec>" << collection << "</setSpec>\n";
189    if (this->configuration->getSetName(collection) != "")
190    {
191      output << utf8convert << "    <setName>" << this->configuration->getSetName(collection) << "</setName>\n";
192    }
193    else
194    {
195      output << utf8convert << "    <setName>" << collection << "</setName>\n";
196    }
197    if (this->configuration->getSetDescription(collection) != "")
198    {
199      output << utf8convert << "    <setDescription>" << this->configuration->getSetDescription(collection) << "</setDescription>\n";
200    }
201    output << utf8convert << "  </set>\n";
202    this->setsOutput++;
203  }
204
205  // Now loop through displaying the next matching records
206  while (set_iterator != sets_response.docInfo.end())
207  {
208    text_t set = (*set_iterator).OID;
209
210    // Only classifiers with supportsmemberof become OAI sets, for reasons I don't really understand
211    text_tset set_metadata;
212    set_metadata.insert("supportsmemberof");
213    set_metadata.insert("Title");
214    FilterResponse_t set_response;
215    get_info(set, collection, "", set_metadata, false, protocol, set_response, *this->logout);
216
217    if (set_response.docInfo[0].metadata["supportsmemberof"].values.size() > 0 && set_response.docInfo[0].metadata["supportsmemberof"].values[0] == "true")
218    {
219      // If we've output the desired number of records return a resumptionToken and we're done
220      if (this->setsOutput == this->configuration->resumeAfter())
221      {
222    ResumptionToken resumption_token("", "", "", "", "", collection + ":" + set);
223
224    // Don't add any whitespace around the resumption token as it can confuse harvesters/validators
225    output << "  <resumptionToken>" << resumption_token.getResumptionTokenString() << "</resumptionToken>" << endl;
226    return false;
227      }
228
229      // Otherwise output this set and increment the count
230      output << utf8convert << "  <set>\n";
231      output << utf8convert << "    <setSpec>" << collection << ":" << set << "</setSpec>\n";
232      if (this->configuration->getSetName(collection + ":" + set) != "")
233      {
234    output << utf8convert << "    <setName>" << this->configuration->getSetName(collection + ":" + set) << "</setName>\n";
235      }
236      else
237      {
238    output << utf8convert << "    <setName>" << set_response.docInfo[0].metadata["Title"].values[0] << "</setName>\n";
239      }
240      if (this->configuration->getSetDescription(collection + ":" + set) != "")
241      {
242    output << utf8convert << "    <setDescription>" << this->configuration->getSetDescription(collection + ":" + set) << "</setDescription>\n";
243      }
244      output << utf8convert << "  </set>\n";
245      this->setsOutput++;
246    }
247
248    set_iterator++;
249  }
250
251  return true;
252}
Note: See TracBrowser for help on using the browser.