root/main/trunk/greenstone2/runtime-src/src/oaiservr/listsetsaction.cpp @ 22739

Revision 22739, 9.3 KB (checked in by mdewsnip, 9 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
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 browser.