root/gsdl/trunk/src/oaiservr/listsetsaction.cpp @ 15428

Revision 15428, 7.1 KB (checked in by mdewsnip, 12 years ago)

Changed all the "OIDtools.h" to "recptprototools.h".

  • Property svn:keywords set to Author Date Id Revision
Line 
1#include "listsetsaction.h"
2
3#if defined(GSDL_USE_STL_H)
4#include <fstream.h>
5#else
6#include <fstream>
7#endif
8
9#include "recptprototools.h"
10#include "oaitools.h"
11
12bool listsetsaction::validateAction(recptproto *protocol, oaiargs &params)
13{
14  int params_size = params.getSize();
15
16  // Remove any parameters that aren't valid for this action
17  text_tmap::const_iterator param_iterator = params.begin();
18  while (param_iterator != params.end())
19  {
20    if (param_iterator->first != "verb" && param_iterator->first != "resumptionToken")
21    {
22      params.erase(param_iterator->first);
23    }
24
25    param_iterator++;
26  }
27
28  if (params_size != params.getSize()) {
29    this->errorType = "badArgument";
30    return false;
31  }
32
33  if (params["resumptionToken"] != "") {
34    ResumptionToken token(params["resumptionToken"]);
35    // TO DO: Resumption token validation checking (the token.isValid() function is useless for ListSets)
36    // if (!token.isValid()) {
37    //   this->errorType = "badResumptionToken";
38    //   return false;
39    // }
40  }
41
42  return true;
43}
44
45bool listsetsaction::output_content(ostream &output, recptproto *protocol, text_tset &collections, oaiargs &params)
46{
47  text_tset::iterator here = collections.begin();
48  text_tset::iterator end  = collections.end();
49  while (here != end) {
50    text_t collect = *here;
51    this->output_content(output, protocol, params);
52    ++here;
53  }
54  return true;
55}
56
57bool listsetsaction::output_content(ostream &output, recptproto *protocol, oaiargs &params)
58{
59  // output the total list of classifier points
60
61  // variables required
62  text_t browseOID = "browse";
63  FilterResponse_t response;
64  comerror_t       err;
65  text_tarray &    collections = this->configuration->getCollectionsList();
66  text_tset        metadata;
67  ofstream         logout("oai.log", ios::app);
68 
69  // get a list of the collections available
70  //  protocol->get_collection_list(collections, err, output);
71  if (collections.size() == 0) {
72    logout << "Found *no* OAI collections - check main.cfg for oaicollection items and read the OAI documentation.\n";
73  }
74
75  // check resumption token
76  int startSet = 0;
77  if (params["resumptionToken"] != "") {
78    ResumptionToken token(params["resumptionToken"]);
79    startSet = token.getPosition() - 1; // first document is said to be 1..
80  }
81  this->replyToken = NULL;
82
83  this->setNumber = 0;
84  this->setsOutput = 0;
85  for(int current_col = 0; current_col < collections.size(); ++current_col) {
86    // output the collection as a set, first, then its children
87    text_t gsdlCollect = collections[current_col];
88
89    if (this->setsOutput == this->configuration->resumeAfter())
90    {
91      this->replyToken = new ResumptionToken("", "", "");
92      this->replyToken->setPosition("", this->setNumber+1);
93      break;
94    }
95
96    if (this->setNumber >= startSet)
97    {
98      output << "  <set>" << endl;
99      output << "    <setSpec>" << gsdlCollect << "</setSpec>" << endl;;
100      output << "    <setName>" << gsdlCollect << "</setName>" << endl;
101      output << "  </set>" << endl;
102      this->setsOutput++;
103    }
104    setNumber++;
105
106    // get all the children of the (relevant) classifier data structures
107    get_children(browseOID, gsdlCollect, "", metadata, false, protocol, response, logout);
108    // and send them to the "recurse_content" list
109    for (int c = 0; c < response.numDocs; ++c) {
110      this->recurse_content(output, protocol, gsdlCollect, response.docInfo[c].OID, gsdlCollect, startSet);
111    }
112  }
113
114  // do a resumption token if required; errors cancel a token...
115  if (this->replyToken != NULL && this->errorType == "") {
116    output << "  <resumptionToken>" << endl;
117    output << "    " << this->replyToken->getToken() << endl;
118    output << "  </resumptionToken>" << endl;
119  }
120
121  return true;
122}
123
124void listsetsaction::recurse_content(ostream &output, recptproto *protocol, text_t &collection,
125                     const text_t &classifier, text_t setHierarchy, int startSet)
126{
127  // metadata for this call
128  FilterResponse_t response;
129  text_tset        metadata;
130  ofstream         logout("oai.log", ios::app);
131
132  if (this->setsOutput == this->configuration->resumeAfter())
133  {
134    this->replyToken = new ResumptionToken("", "", "");
135    this->replyToken->setPosition("", this->setNumber+1);
136    return;
137  }
138
139  metadata.insert("contains");
140  metadata.insert("Title");
141  metadata.insert("supportsmemberof");
142
143  // get the document information
144  if (!get_info(classifier, collection, "", metadata, false, protocol, response, logout)) {
145    //cerr << "recurse content: Bad identifier or protocol " << classifier << endl;
146    return;
147  }
148
149  // check for top-level classifiers, check if the set name includes a '.'; if
150  // not, it is a top-level classifier: check for memberof support.  Those without
151  // memberof support will not be supported on OAI
152  if (findchar(classifier.begin(), classifier.end(), '.') == classifier.end()) {
153    if (response.docInfo[0].metadata["supportsmemberof"].values.size() > 0) {
154      text_t memberOf = response.docInfo[0].metadata["supportsmemberof"].values[0];
155      if (memberOf != "true") {
156    return;
157      }
158    }
159    else {
160      return;
161    }
162  }
163
164  MetadataInfo_tmap::iterator here = response.docInfo[0].metadata.begin();
165  MetadataInfo_tmap::iterator end  = response.docInfo[0].metadata.end();
166  text_t title;
167
168  while (here != end)
169  {
170    // Each set should only have one title - hence we only output one title here
171    // (it is a set title, not a collection)
172    if (here->first == "Title" && here->second.values.size() > 0) {
173      title = here->second.values[0];
174    }
175
176    ++here;
177  }
178
179  // output the xml for this set; use the classifier id for the name
180  // if the title is blank
181  // curSet holds the colon-separated sequence of parent sets of the current set
182  text_t curSet;
183  if (this->setNumber >= startSet)
184  {
185    output << "  <set>" << endl;
186    text_t oai_classifier = classifier;
187    oaiclassifier::toOAI(collection, oai_classifier);
188    output << "    <setSpec>" << oai_classifier << "</setSpec>" << endl;
189    output << "    <setName>";
190    if (!title.empty()) {
191      curSet = setHierarchy + ":" + title;
192    }
193    else {
194      curSet = classifier; // Pretty much never gets here (shouldn't, at least)
195    }
196    output << curSet;
197    output << "</setName>" << endl;
198    output << "  </set>" << endl;
199    this->setsOutput++;
200  }
201  this->setNumber++;
202
203  // get the children of this classifier and iterate them
204  get_children(classifier, collection, "", metadata, false, protocol, response, logout);
205  for (int c = 0; c < response.numDocs; ++c) {
206    text_t child = response.docInfo[c].OID;
207
208    if (child == classifier)
209      continue;
210
211    // check for non classifier items and exclude them
212    text_t childHead;
213    text_t::const_iterator start = child.begin();
214    text_t::const_iterator here  = child.begin();
215    here += 2;
216    childHead = substr(start, here);
217
218    if (childHead != "CL")
219      continue;
220
221    // Recurse for "proper" classifier children. Pass curSet, the colon-separated list of
222    // parent sets. curSet is pass-by-value, so that as we step out of recursion we remember
223    // old set hierarchies.
224    this->recurse_content(output, protocol, collection, child, curSet, startSet);
225  }
226 
227  return;
228}
Note: See TracBrowser for help on using the browser.