root/main/trunk/greenstone2/runtime-src/src/oaiservr/listrecsaction.cpp @ 24412

Revision 24412, 8.1 KB (checked in by ak19, 9 years ago)

Fixed a new failure of the OAI validation test of GS2's OAI server: where list records is given an Until date that is earlier than the earliestDatestamp. Needs to return a noRecordsMatch. It does now. The calculation of the earliestDatestamp is now shifted to the oaiaction.cpp superclass and called by both identifyaction and listrecordsaction for the identify and listrecords OAI queries, since these tasks need to work with earliestDatestamp.

  • Property svn:keywords set to Author Date Id Revision
Line 
1/**********************************************************************
2 *
3 * listrecsaction.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 "listrecsaction.h"
28
29#include "oaitools.h"
30#include "recordaction.h"
31
32bool listrecsaction::validateAction(recptproto *protocol, oaiargs &params)
33{
34  // ----------------------------------------------------------------------------
35  //  1. Check for invalid arguments
36  // ----------------------------------------------------------------------------
37  bool invalid_argument_supplied = false;
38  text_tmap::const_iterator param_iterator = params.begin();
39  while (param_iterator != params.end())
40  {
41    // Check for arguments that aren't valid for this action
42    if (param_iterator->first != "verb" &&
43    param_iterator->first != "from" &&
44    param_iterator->first != "until" &&
45    param_iterator->first != "set" &&
46    param_iterator->first != "resumptionToken" &&
47    param_iterator->first != "metadataPrefix")
48    {
49      // We've found an invalid argument
50      invalid_argument_supplied = true;
51
52      // Delete the invalid argument from the list so it doesn't end up in the <request> tag that is returned
53      params.erase(param_iterator->first);
54    }
55
56    param_iterator++;
57  }
58
59  // If we found an invalid argument it's an error, so don't go any further
60  if (invalid_argument_supplied)
61  {
62    this->errorType = "badArgument";
63    return false;
64  }
65
66  // ----------------------------------------------------------------------------
67  //  2. Handle any exclusive arguments
68  // ----------------------------------------------------------------------------
69
70  //  The resumptionToken argument is exclusive
71  if (params["resumptionToken"] != "")
72  {
73    // This argument is exclusive, so no other arguments are allowed (except "verb" of course)
74    if (params.getSize() != 2)
75    {
76      this->errorType = "badArgument";
77      return false;
78    }
79
80    // Check the resumption token is valid
81    ResumptionToken token(params["resumptionToken"]);
82    if (token.isValid())
83    {
84      // Everything is fine, and we don't continue further because this is an exclusive argument
85      this->errorType = "";
86      return true;
87    }
88    else
89    {
90      // There was an error with the resumption token
91      this->errorType = "badResumptionToken";
92      return false;
93    }
94  }
95
96  // ----------------------------------------------------------------------------
97  //  3. Handle any required arguments
98  // ----------------------------------------------------------------------------
99
100  // The metadataPrefix is required
101  text_t metadataPrefix = params["metadataPrefix"];
102
103  // Check that the metadataPrefix argument exists
104  if (metadataPrefix == "")
105  {
106    this->errorType = "badArgument";
107    return false;
108  }
109
110  // Check that the metadataPrefix is a format we support
111  if (this->formatNotSupported(metadataPrefix))
112  {
113    this->errorType = "cannotDisseminateFormat";
114    return false;
115  }
116
117  // ----------------------------------------------------------------------------
118  // 4. Check any remaining arguments
119  // ----------------------------------------------------------------------------
120
121  // Check "from" and "until" arguments
122  if (params["from"] != "" || params["until"] != "")
123  {
124    text_t from  = params["from"];
125    text_t until = params["until"];
126
127    // Check the from date is in the correct format: YYYY-MM-DD
128    if (from != "")
129    {
130      // Must be in the form YYYY-MM-DD
131      if (from.size() != 10 || from[4] != '-' || from[7] != '-')
132      {
133    this->errorType = "badArgument";
134    params.erase("from");
135      }
136    }
137    // Check the until date is in the correct format: YYYY-MM-DD
138    if (until != "")
139    {
140      // Must be in the form YYYY-MM-DD
141      if (until.size() != 10 || until[4] != '-' || until[7] != '-')
142      {
143    this->errorType = "badArgument";
144    params.erase("until");
145      }
146    }
147
148    if (this->errorType == "badArgument")
149    {
150      return false;
151    }
152
153    // If both arguments are supplied the from date must be less than or equal to the until date
154    if (from != "" && until != "" && !(from <= until))
155    {
156      this->errorType = "badArgument";
157      return false;
158    }   
159  }
160
161  // Check "set" argument
162  if (params["set"] != "")
163  {
164    // Example set specification: "demo:CL2"
165    text_t set = params["set"];
166
167    // Extract the collection name from the set specification
168    text_t collection = "";
169    oaiclassifier::toGSDL(collection, set);
170
171    // Check that the collection is accessible
172    ColInfoResponse_t cinfo;
173    comerror_t err;
174    protocol->get_collectinfo(collection, cinfo, err, cerr);
175    if (err != noError)
176    {
177      this->errorType = "badArgument";
178      return false;
179    }
180   
181    // Check the collection is one that is in the list in the oai.cfg file
182    text_tarray &collections = this->configuration->getCollectionsList();
183    bool collection_found = false;
184    for (int c = 0; c < collections.size(); c++)
185    {
186      if (collections[c] == collection)
187      {
188    collection_found = true;
189    break;
190      }
191    }
192
193    // The collection was not found
194    if (!collection_found)
195    {
196      this->errorType = "badArgument";
197      return false;
198    }
199
200    // Check the child set if it was given
201    if (set != "" && !this->check_classifier(protocol, collection, set))
202    {
203      this->errorType = "badArgument";
204      return false;
205    }
206   
207    // check we're not requested to retrieve records of *this* set/coll
208    // from an earlier date than *this* set's earliestdatestamp
209    if (params["until"] != "") {
210        text_t eDatestamp = cinfo.earliestDatestamp;
211        time_t raw_time = (time_t)eDatestamp.getint();
212        eDatestamp = this->parseDatestamp(raw_time);
213       
214        // error if request is for records of an earlier date than this coll/set's earliestDatestamp       
215        if(params["until"] < eDatestamp) {
216            this->errorType = "noRecordsMatch"; // for *this* set/coll of the repository
217            return false;
218        }
219    }
220   
221  } else { // no set (collection) specified
222     if (params ["until"] != "") {  // check we're not requested to retrieve records of an earlier
223                                    // date than the earliestdatestamp across all collections/sets
224        // John Thompson advises not to do lazy evaluation of earliestDatestamp here, because
225        // reading x number of build.cfg files for x number of collections to work out the
226        // earliestDatestamp among them is not too expensive an operation, but we do want the OAI
227        // Server to give accurate results when queried, as that's specified by the OAI protocol.
228        //if(this->mEarliestDatestamp == "") {
229        text_t eDatestamp = this->calcEarliestDatestamp(protocol, params);
230        //}
231       
232        if(params["until"] < eDatestamp) { // request is for records of an earlier date than earliestDatestamp     
233            this->errorType = "noRecordsMatch";
234            return false;
235        }       
236     }
237  }
238
239  // If we've reached here everything must be fine
240  this->errorType = "";
241  return true;
242}
243
244//-----------------------------------------------------------------------------------------------
245
246bool listrecsaction::output_document(ostream &output, recptproto *protocol, const text_t &collection,
247             const text_t &OID, const text_t &metadataPrefix)
248{
249  this->record_action->output_record(output, protocol, collection, OID, metadataPrefix);
250  return true;
251}
252 
253//-----------------------------------------------------------------------------------------------
254
255
256
Note: See TracBrowser for help on using the browser.