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

Last change on this file since 24412 was 24412, checked in by ak19, 13 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
File size: 8.1 KB
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 repository browser.