source: gsdl/trunk/runtime-src/src/oaiservr/oaiconfig.cpp@ 20629

Last change on this file since 20629 was 20629, checked in by mdewsnip, 13 years ago

Added new "oaisetname" and "oaisetdescription" configuration options in the oai.cfg file, for setting the setName and setDescription values in the ListSets response.

  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1#include "oaiconfig.h"
2#include <iostream>
3#include "fileutil.h"
4
5
6/**
7 * The mapping works as follows in the oai.cfg or collect.cfg file.
8 *
9 * A line is in the format oaimapping <collection field> <oai field>
10 *
11 * The map here is used to look up the "Greenstone" name which is mapped from
12 * a given OAI field name, the reverse direction to that given in the
13 * Greenstone collect.cfg file. The oairecordaction class instance which
14 * produces output for an OAI record information request thus uses the map
15 * to work from the field in the collection it has on hand which OAI
16 * record name it should use instead.
17 *
18 * An extension is to be used for this in which the OAI field name in the
19 * collect.cfg file can be made specific for a particular record format.
20 * This is done using the OAI field name in the format of
21 * <OAI format>.<OAI field name>
22 * Thus, an rfc1807 Title field would be referred to as rfc1807.Title
23 *
24 * A collection-level mapping can be provided in oai.cfg by prepending
25 * collname to collection field:
26 * <collname:field> <oai field>
27
28 * In the absence of a particular format name, the mapping is taken to be
29 * universal.
30 */
31
32oaiconfig::oaiconfig() : configurable () {
33 this->resumptionSize = -1; // Default = do not use resumption tokens
34}
35
36oaiconfig::oaiconfig(text_t &gsdlhome, text_t &gsdlcollect)
37{
38 // read main configuration file (oai.cfg) to get oai collections
39 text_t mainconfig = filename_cat(gsdlhome, "etc", "oai.cfg");
40 this->collection = "";
41 this->resumptionSize = -1;
42 this->read_configfile(mainconfig);
43
44 // then if we've not got a specified collection in the gsdlcollect
45 // parameter, read in all the collection's individual configurations
46 if (gsdlcollect == "") {
47 text_tarray::iterator start = this->collectList.begin();
48 text_tarray::iterator here = this->collectList.end()-1;
49 while (here != start) {
50 if (!this->configureCollection(gsdlhome, *here)) {
51 this->collectList.erase(here);
52 }
53 --here;
54 }
55 // and do the first one
56 if (!this->configureCollection(gsdlhome, *here)) {
57 this->collectList.erase(here);
58 }
59
60 }
61 else {
62 // what do we do if this fails?
63 this->configureCollection(gsdlhome, gsdlcollect);
64 }
65}
66
67oaiconfig::~oaiconfig()
68{
69 oaicollectmap::iterator here = this->collectMap.begin();
70 oaicollectmap::iterator end = this->collectMap.end();
71 while (here != end) {
72 delete here->second;
73 ++here;
74 }
75}
76
77int oaiconfig::resumeAfter()
78{ return this->resumptionSize;
79}
80
81int oaiconfig::getOAIVersion()
82{
83 if (this->oaiVersion == "1.1") {
84 return 110;
85 }
86 return 200;
87}
88
89bool oaiconfig::configureCollection(const text_t &gsdlhome, const text_t &gsdlcollect)
90{
91 text_t cnfgfile = filename_cat(gsdlhome, "collect", gsdlcollect, "etc", "collect.cfg");
92 if (!file_exists(cnfgfile)) {
93 return false;
94 }
95 this->collection = gsdlcollect;
96 this->read_configfile(cnfgfile);
97
98 return true;
99}
100void oaiconfig::configure (const text_t &key, const text_tarray &cfgline)
101{
102 // we've got an oai mapping item, and at least two fields
103 if (key == "oaimapping" && cfgline.size() > 1) {
104 text_t::const_iterator colonAt;
105 text_t index, name, configCollection;
106
107 // Take a default collection as being whatever the collection being configured is...
108 configCollection = this->collection;
109
110 // get the name of the (collection) field to map; this may actually
111 // be in a colon separated format of the type
112 // <collection name>:<field name>
113 index = cfgline[0];
114 if ((colonAt = findchar(index.begin(), index.end(), ':')) != index.end()) {
115 configCollection = substr(index.begin(), colonAt);
116
117 if (this->collection != "" && configCollection != this->collection) {
118 cerr << "Attempt to configure OAI mappings for " << configCollection << " in " << this->collection << endl;
119 }
120
121 colonAt += 1;
122 index = substr(colonAt, index.end());
123 }
124
125 // the second parameter is the metadata field to map the collection
126 // field onto. It may be provided with a metadata protocol (which
127 // will be given first and separated by a period or full stop). In
128 // the case of format.field name, the splitting is done here.
129 if ((colonAt = findchar(cfgline[1].begin(), cfgline[1].end(), '.')) != cfgline[1].end()) {
130 text_t stub = substr(cfgline[1].begin(), colonAt);
131 colonAt += 1;
132 name = substr(colonAt, cfgline[1].end());
133 index.append(":");
134 index.append(stub);
135 }
136 else {
137 name = cfgline[1];
138 }
139
140 // now 'index' is in the form <collectionfield>:(formatname)
141 // 'name' is simply the fieldname within the format
142 // 'configCollection' is the collection to be configured
143
144 // now simply map the field name (index) onto the collection name (name)
145 if (this->collectMap[configCollection] == NULL) {
146 this->collectMap[configCollection] = new oaicollectconfig(configCollection);
147 }
148 this->collectMap[configCollection]->fieldMap[index] = name;
149
150 // cerr << "Mapping " << index << " to " << name << " in " << configCollection << endl;
151
152 // TODO: check that the mapped field is actually in use
153 }
154 else if (key == "oaicollection" && cfgline.size() >= 1) {
155 // Configure a collection to be used as part of the OAI archive.
156 // This line should read:
157 //
158 // oaicollection <collectionname>
159 //
160 // Where <collectionname> is the name of the directory inside the
161 // gsdl/collect folder which contains the collection.
162 //
163 // To configure several collections, merely repeat this line,
164 // or alternatively use additional collection names after the
165 // first one.
166 //
167 // This configuration should only appear in oai.cfg
168 //
169 if (this->collection != "") {
170 cerr << "Attempt to configure an oai collection outside of oai.cfg" << endl;
171 cerr << "Configuration attempted in " << this->collection << " collection." << endl;
172 exit(1);
173 }
174 for (int c = 0; c < cfgline.size(); ++c) {
175 this->collectList.push_back(cfgline[c]);
176 }
177 }
178 else if (key == "oaimetadata" && cfgline.size() >= 1) {
179 // List of metadata prefixes to suuport
180 // This line should read:
181 //
182 // oaicollection <metadataname> <metadataname>...
183 //
184 //
185 // This configuration should only appear in oai.cfg
186 //
187 if (this->collection != "") {
188 cerr << "Attempt to configure oai metadata outside of oai.cfg" << endl;
189 cerr << "Configuration attempted in " << this->collection << " collection." << endl;
190 exit(1);
191 }
192 for (int c = 0; c < cfgline.size(); ++c) {
193 // todo: check that the set name is valid
194 this->metadataSet.insert(cfgline[c]);
195 }
196 }
197 else if (key == "oaiinfo" && cfgline.size() >= 1) {
198 // Get a piece of information for the oai repository information
199 // request. The line should read:
200 //
201 // oaiinfo <information field name> <value>
202 //
203 // This configuration should only be attempted in oai.cfg
204 //
205 if (this->collection != "") {
206 cerr << "Attempt to set oai information outside of oai.cfg" << endl;
207 cerr << "Configuration attempted in " << this->collection << " collection." << endl;
208 exit(1);
209 }
210
211 // if no second parameter is given, then the first parameter
212 if (cfgline.size() == 1) {
213 this->infoMap[cfgline[0]] = cfgline[0];
214 }
215 else {
216 this->infoMap[cfgline[0]] = cfgline[1];
217 }
218 }
219 else if (key == "oaisetname" && cfgline.size() == 2) {
220 this->setNameMap[cfgline[0]] = cfgline[1];
221 }
222 else if (key == "oaisetdescription" && cfgline.size() == 2) {
223 this->setDescriptionMap[cfgline[0]] = cfgline[1];
224 }
225 else if (key == "oaiversion" && cfgline.size() >= 1) {
226 this->oaiVersion = cfgline[0];
227 }
228 else if (key == "resumeafter" && cfgline.size() >= 1) {
229 this->resumptionSize = cfgline[0].getint();
230 }
231 // get and note a maintainer item to support the Identify Verb of OAI
232 else if (key == "maintainer" && cfgline.size() >= 1) {
233 int line = 0;
234
235 // TODO: exhaustive checks for empty or default values of maintainer
236 while (line < cfgline.size()) {
237 if (cfgline[line] != "NULL" &&
238 cfgline[line] != "") {
239 // do something
240 break;
241 }
242 else {
243 ++line;
244 }
245 }
246
247 // Only try to set the configuration if we have a legitimate value ...
248 if (line < cfgline.size()) {
249 // ensure we have a map to write to
250 if (this->collectMap[this->collection] == NULL) {
251 this->collectMap[this->collection] = new oaicollectconfig(this->collection);
252 }
253 this->collectMap[this->collection]->maintainer = cfgline[line];
254 }
255 }
256 else if (key == "repositoryName" && cfgline.size() >= 1) {
257 int line = 0;
258
259 // TODO: exhaustive checks for empty or default values of repositoryName
260 while (line < cfgline.size()) {
261 if (cfgline[line] != "NULL" &&
262 cfgline[line] != "") {
263 // do something
264 break;
265 }
266 else {
267 ++line;
268 }
269 }
270
271 // Only try to set the configuration if we have a legitimate value ...
272 if (line < cfgline.size()) {
273 // ensure we have a map to write to
274 if (this->collectMap[this->collection] == NULL) {
275 this->collectMap[this->collection] = new oaicollectconfig(this->collection);
276 }
277 this->collectMap[this->collection]->repositoryName = cfgline[line];
278 }
279 }
280 else if (key == "baseURL" && cfgline.size() >= 1) {
281 int line = 0;
282
283 while (line < cfgline.size()) {
284 if (cfgline[line] != "NULL" &&
285 cfgline[line] != "") {
286 // do something
287 break;
288 }
289 else {
290 ++line;
291 }
292 }
293
294 // Only try to set the configuration if we have a legitimate value ...
295 if (line < cfgline.size()) {
296 // ensure we have a map to write to
297 if (this->collectMap[this->collection] == NULL) {
298 this->collectMap[this->collection] = new oaicollectconfig(this->collection);
299 }
300 this->collectMap[this->collection]->baseURL = cfgline[line];
301 }
302 }
303 else if (key == "baseDocRoot" && cfgline.size() >= 1) {
304 int line = 0;
305
306 while (line < cfgline.size()) {
307 if (cfgline[line] != "NULL" &&
308 cfgline[line] != "") {
309 // do something
310 break;
311 }
312 else {
313 ++line;
314 }
315 }
316
317 // Only try to set the configuration if we have a legitimate value ...
318 if (line < cfgline.size()) {
319 // ensure we have a map to write to
320 if (this->collectMap[this->collection] == NULL) {
321 this->collectMap[this->collection] = new oaicollectconfig(this->collection);
322 }
323 this->collectMap[this->collection]->baseDocRoot = cfgline[line];
324 }
325 }
326}
327
328/**
329 * TODO: store all field values in a map per collection
330 */
331text_t oaiconfig::getCollectionConfig(const text_t &collection, const text_t &field)
332{
333 if (this->collectMap[collection] == NULL) {
334 return "";
335 }
336 if (field == "maintainer") {
337 return this->collectMap[collection]->maintainer;
338 }
339
340 if (field == "repositoryName") {
341 return this->collectMap[collection]->repositoryName;
342 }
343
344 if (field == "baseURL") {
345 return this->collectMap[collection]->baseURL;
346 }
347
348 if (field == "baseDocRoot") {
349 return this->collectMap[collection]->baseDocRoot;
350 }
351
352 return "";
353}
354
355text_t oaiconfig::getMapping(const text_t &collection, const text_t &collectfield)
356{
357 if (this->collectMap[collection] == NULL) {
358 return "";
359 }
360 return this->collectMap[collection]->fieldMap[collectfield];
361}
362
363/**
364 * Get the mapping for a field in a given collection; if no mapping
365 * exists, the result will be a blank string.
366 */
367text_t oaiconfig::getMapping(const text_t &collection, const text_t &collectfield, const text_t &formatname)
368{
369 text_t fullName = collectfield;
370 fullName.append(":");
371 fullName.append(formatname);
372
373 // try the collection-specific options first
374 if (this->collectMap[collection] != NULL) {
375 // first try the most specific item - this collection, and given that protocol
376 if (this->collectMap[collection]->fieldMap.count(fullName) >= 1) {
377 return this->collectMap[collection]->fieldMap[fullName];
378 }
379 // otherwise, fall back to this collection, and all protocols
380 else if (this->collectMap[collection]->fieldMap.count(collectfield) >= 1) {
381 return this->collectMap[collection]->fieldMap[collectfield];
382 }
383 }
384
385 // if no mappings exist, return an empty item
386 if (this->collectMap[""] == NULL) {
387 return "";
388 }
389
390 // then try generic rules
391 if (this->collectMap[""]->fieldMap.count(fullName) >= 1) {
392 return this->collectMap[""]->fieldMap[fullName];
393 }
394 else {
395 return this->collectMap[""]->fieldMap[collectfield];
396 }
397}
398
399
400text_t oaiconfig::getSetName(const text_t &setSpec)
401{
402 if (setNameMap.find(setSpec) != setNameMap.end())
403 {
404 return setNameMap[setSpec];
405 }
406
407 return "";
408}
409
410
411text_t oaiconfig::getSetDescription(const text_t &setSpec)
412{
413 if (setDescriptionMap.find(setSpec) != setDescriptionMap.end())
414 {
415 return setDescriptionMap[setSpec];
416 }
417
418 return "";
419}
Note: See TracBrowser for help on using the repository browser.