/********************************************************************** * * listsetsaction.cpp -- * * Copyright (C) 2004-2010 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ #include "listsetsaction.h" #include "resumptiontoken.h" #include "recptprototools.h" #include "oaitools.h" bool listsetsaction::validateAction(recptproto *protocol, oaiargs ¶ms) { // ---------------------------------------------------------------------------- // 1. Check for invalid arguments // ---------------------------------------------------------------------------- bool invalid_argument_supplied = false; text_tmap::const_iterator param_iterator = params.begin(); while (param_iterator != params.end()) { // Check for arguments that aren't valid for this action if (param_iterator->first != "verb" && param_iterator->first != "resumptionToken") { // We've found an invalid argument invalid_argument_supplied = true; // Delete the invalid argument from the list so it doesn't end up in the tag that is returned params.erase(param_iterator->first); } param_iterator++; } // If we found an invalid argument it's an error, so don't go any further if (invalid_argument_supplied) { this->errorType = "badArgument"; return false; } // ---------------------------------------------------------------------------- // 2. Handle any exclusive arguments // ---------------------------------------------------------------------------- // The resumptionToken argument is exclusive if (params["resumptionToken"] != "") { // This argument is exclusive, so no other arguments are allowed (except "verb" of course) if (params.getSize() != 2) { this->errorType = "badArgument"; return false; } // Check the resumption token is valid ResumptionToken token(params["resumptionToken"]); if (token.isValid()) { // Everything is fine, and we don't continue further because this is an exclusive argument this->errorType = ""; return true; } else { // There was an error with the resumption token this->errorType = "badResumptionToken"; return false; } } // ---------------------------------------------------------------------------- // 3. Handle any required arguments // ---------------------------------------------------------------------------- // None! // ---------------------------------------------------------------------------- // 4. Check any remaining arguments // ---------------------------------------------------------------------------- // None! // If we've reached here everything must be fine this->errorType = ""; return true; } bool listsetsaction::output_content(ostream &output, recptproto *protocol, oaiargs ¶ms) { // Reset variables this->setsOutput = 0; text_t position = ""; // Process the resumptionToken if there is one if (params["resumptionToken"] != "") { ResumptionToken resumption_token(params["resumptionToken"]); position = resumption_token.getPosition(); } // Get a list of the collections available text_tarray& collections = this->configuration->getCollectionsList(); if (collections.size() == 0) { return false; } // Get the current collection from the position value text_t collection_name = ""; oaiclassifier::toGSDL(collection_name, position); // Find the starting collection text_tarray::iterator collection_iterator = collections.begin(); while (collection_iterator != collections.end()) { if (collection_name == "" || collection_name == *collection_iterator) { break; } collection_iterator++; } // Now loop through the remaining collections while (collection_iterator != collections.end()) { collection_name = (*collection_iterator); // If we've output the desired number of records return a resumptionToken and we're done if (this->setsOutput == this->configuration->resumeAfter()) { ResumptionToken resumption_token("", "", "", "", "", collection_name); // Don't add any whitespace around the resumption token as it can confuse harvesters/validators output << " " << resumption_token.getResumptionTokenString() << "" << endl; return true; } // If output_content_for_col() returns false a resumption token has been output, so it's time to stop if (output_content_for_col(output, protocol, params, collection_name) == false) { return true; } collection_iterator++; } return true; } bool listsetsaction::output_content_for_col(ostream &output, recptproto *protocol, oaiargs ¶ms, text_t collection) { utf8outconvertclass utf8convert; text_t position = ""; // Process the resumptionToken if there is one if (params["resumptionToken"] != "") { ResumptionToken resumption_token(params["resumptionToken"]); position = resumption_token.getPosition(); } // Get the list of sets in this collection // Collections should not contain too many sets otherwise this will use a lot of time and memory text_tset metadata; // Must be empty for efficiency FilterResponse_t sets_response; get_children("browse", collection, "", metadata, false, protocol, sets_response, *this->logout); // Find the starting position, if necessary ResultDocInfo_tarray::iterator set_iterator = sets_response.docInfo.begin(); if (this->setsOutput == 0) { while (set_iterator != sets_response.docInfo.end()) { if (position == "" || position == (collection + ":" + (*set_iterator).OID)) { break; } set_iterator++; } } // Output the collection as a set if (position == "" || position == collection) { output << utf8convert << " \n"; output << utf8convert << " " << collection << "\n"; if (this->configuration->getSetName(collection) != "") { output << utf8convert << " " << this->configuration->getSetName(collection) << "\n"; } else { output << utf8convert << " " << collection << "\n"; } if (this->configuration->getSetDescription(collection) != "") { output << utf8convert << " " << this->configuration->getSetDescription(collection) << "\n"; } output << utf8convert << " \n"; this->setsOutput++; } // Now loop through displaying the next matching records while (set_iterator != sets_response.docInfo.end()) { text_t set = (*set_iterator).OID; // Only classifiers with supportsmemberof become OAI sets, for reasons I don't really understand text_tset set_metadata; set_metadata.insert("supportsmemberof"); set_metadata.insert("Title"); FilterResponse_t set_response; get_info(set, collection, "", set_metadata, false, protocol, set_response, *this->logout); if (set_response.docInfo[0].metadata["supportsmemberof"].values.size() > 0 && set_response.docInfo[0].metadata["supportsmemberof"].values[0] == "true") { // If we've output the desired number of records return a resumptionToken and we're done if (this->setsOutput == this->configuration->resumeAfter()) { ResumptionToken resumption_token("", "", "", "", "", collection + ":" + set); // Don't add any whitespace around the resumption token as it can confuse harvesters/validators output << " " << resumption_token.getResumptionTokenString() << "" << endl; return false; } // Otherwise output this set and increment the count output << utf8convert << " \n"; output << utf8convert << " " << collection << ":" << set << "\n"; if (this->configuration->getSetName(collection + ":" + set) != "") { output << utf8convert << " " << this->configuration->getSetName(collection + ":" + set) << "\n"; } else { output << utf8convert << " " << set_response.docInfo[0].metadata["Title"].values[0] << "\n"; } if (this->configuration->getSetDescription(collection + ":" + set) != "") { output << utf8convert << " " << this->configuration->getSetDescription(collection + ":" + set) << "\n"; } output << utf8convert << " \n"; this->setsOutput++; } set_iterator++; } return true; }