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

Last change on this file since 22212 was 22212, checked in by kjdon, 14 years ago

tidied up the config classes. moved all the global params into oaiconfig instead of having them in the collection map. put setname and description into the collection map instead of having their own maps. Added methods to access baseURL etc

  • Property svn:keywords set to Author Date Id Revision
File size: 10.8 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" || key == "oaisetdescription") {
221 text_t coll_name;
222 text_t value = "";
223 if (this->collection != "") {
224 // we are in collect.cfg
225 coll_name = this->collection;
226 if (cfgline.size() == 1) {
227 // just the collection value
228 value = cfgline[0];
229 }
230 else if (cfgline.size() == 2) {
231 // we have a subset name (eg for classifier)
232 coll_name.append(":");
233 coll_name.append(cfgline[0]);
234 value = cfgline[1];
235 }
236 } else if (cfgline.size() == 2) {
237 // oai.cfg, line should be collname, setName
238 coll_name = cfgline[0];
239 value = cfgline[1];
240 }
241 if (value != "") {
242 if (this->collectMap[coll_name] == NULL) {
243 this->collectMap[coll_name] = new oaicollectconfig(coll_name);
244 }
245 if (key == "oaisetname") {
246 this->collectMap[coll_name]->setName = value;
247 } else if (key == "oaisetdescription") {
248 this->collectMap[coll_name]->setDescription = value;
249 }
250 }
251 }
252
253 else if (key == "resumeafter" && cfgline.size() >= 1) {
254 this->resumptionSize = cfgline[0].getint();
255 }
256
257 else if (key == "maintainer") {
258 this->maintainer = cfgline[0];
259 }
260 else if (key == "repositoryName") {
261 this->repositoryName = cfgline[0];
262 }
263 else if (key == "baseURL") {
264 this->baseURL = cfgline[0];
265 }
266 else if (key == "baseLibraryURL") {
267 this->baseLibraryURL = cfgline[0];
268 }
269 else if (key == "baseDocRoot") {
270 this->baseDocRoot = cfgline[0];
271 }
272
273}
274
275
276text_t oaiconfig::getMapping(const text_t &collection, const text_t &collectfield)
277{
278 if (this->collectMap[collection] == NULL) {
279 return "";
280 }
281 return this->collectMap[collection]->fieldMap[collectfield];
282}
283
284/**
285 * Get the mapping for a field in a given collection; if no mapping
286 * exists, the result will be a blank string.
287 */
288text_t oaiconfig::getMapping(const text_t &collection, const text_t &collectfield, const text_t &formatname)
289{
290 text_t fullName = collectfield;
291 fullName.append(":");
292 fullName.append(formatname);
293
294 // try the collection-specific options first
295 if (this->collectMap[collection] != NULL) {
296 // first try the most specific item - this collection, and given that protocol
297 if (this->collectMap[collection]->fieldMap.count(fullName) >= 1) {
298 return this->collectMap[collection]->fieldMap[fullName];
299 }
300 // otherwise, fall back to this collection, and all protocols
301 else if (this->collectMap[collection]->fieldMap.count(collectfield) >= 1) {
302 return this->collectMap[collection]->fieldMap[collectfield];
303 }
304 }
305
306 // if no mappings exist, return an empty item
307 if (this->collectMap[""] == NULL) {
308 return "";
309 }
310
311 // then try generic rules
312 if (this->collectMap[""]->fieldMap.count(fullName) >= 1) {
313 return this->collectMap[""]->fieldMap[fullName];
314 }
315 else {
316 return this->collectMap[""]->fieldMap[collectfield];
317 }
318}
319
320text_t oaiconfig::getBaseURL()
321{
322 return this->baseURL;
323}
324text_t oaiconfig::getBaseLibraryURL()
325{
326 return this->baseLibraryURL;
327}
328text_t oaiconfig::getBaseDocRoot()
329{
330 return this->baseDocRoot;
331}
332text_t oaiconfig::getRepositoryName()
333{
334 return this->repositoryName;
335}
336text_t oaiconfig::getMaintainer()
337{
338 return this->maintainer;
339}
340text_t oaiconfig::getSetName(const text_t &setSpec)
341{
342 if (this->collectMap[setSpec] == NULL) {
343 return "" ;
344 }
345
346 return this->collectMap[setSpec]->setName;
347
348}
349
350text_t oaiconfig::getSetDescription(const text_t &setSpec)
351{
352 if (this->collectMap[setSpec] == NULL) {
353 return "" ;
354 }
355
356 return this->collectMap[setSpec]->setDescription;
357}
358
Note: See TracBrowser for help on using the repository browser.