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

Last change on this file since 20827 was 20827, checked in by oranfry, 11 years ago

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

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