root/gsdl/trunk/runtime-src/src/oaiservr/oaiconfig.cpp @ 20827

Revision 20827, 12.7 KB (checked in by oranfry, 10 years ago)

Added in stdlib.h header file so the compiler can find exit()

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