source: gsdl/trunk/src/oaiservr/listsetsaction.cpp@ 15428

Last change on this file since 15428 was 15428, checked in by mdewsnip, 16 years ago

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

  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
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 repository browser.