source: main/trunk/greenstone2/runtime-src/src/oaiservr/oaiconfig.cpp@ 23233

Last change on this file since 23233 was 23233, checked in by kjdon, 13 years ago

changed the url info stored in oai.cfg. Now have one optional field for web server url. Will be automatically generated if not specified. Then there are relative paths for oaiserver, library and doc root.

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