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

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

new toOID takes an extra arg, repos_id, so its generates ids like oai:repos-id:collname:doc-id. old version is still used for set spec ids which remain like demo:CL5. another method to extrac the collection name from a full id

  • Property svn:keywords set to Author Date Id Revision
File size: 11.2 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 == "repositoryId") {
264 this->repositoryId = cfgline[0];
265 }
266 else if (key == "repositoryIdVersion") {
267 this->repositoryIdVersion = cfgline[0];
268 }
269 else if (key == "baseURL") {
270 this->baseURL = cfgline[0];
271 }
272 else if (key == "baseLibraryURL") {
273 this->baseLibraryURL = cfgline[0];
274 }
275 else if (key == "baseDocRoot") {
276 this->baseDocRoot = cfgline[0];
277 }
278 else if (key == "oaiversion") {
279 this->oaiVersion = cfgline[0];
280 }
281
282}
283
284
285text_t oaiconfig::getMapping(const text_t &collection, const text_t &collectfield)
286{
287 if (this->collectMap[collection] == NULL) {
288 return "";
289 }
290 return this->collectMap[collection]->fieldMap[collectfield];
291}
292
293/**
294 * Get the mapping for a field in a given collection; if no mapping
295 * exists, the result will be a blank string.
296 */
297text_t oaiconfig::getMapping(const text_t &collection, const text_t &collectfield, const text_t &formatname)
298{
299 text_t fullName = collectfield;
300 fullName.append(":");
301 fullName.append(formatname);
302
303 // try the collection-specific options first
304 if (this->collectMap[collection] != NULL) {
305 // first try the most specific item - this collection, and given that protocol
306 if (this->collectMap[collection]->fieldMap.count(fullName) >= 1) {
307 return this->collectMap[collection]->fieldMap[fullName];
308 }
309 // otherwise, fall back to this collection, and all protocols
310 else if (this->collectMap[collection]->fieldMap.count(collectfield) >= 1) {
311 return this->collectMap[collection]->fieldMap[collectfield];
312 }
313 }
314
315 // if no mappings exist, return an empty item
316 if (this->collectMap[""] == NULL) {
317 return "";
318 }
319
320 // then try generic rules
321 if (this->collectMap[""]->fieldMap.count(fullName) >= 1) {
322 return this->collectMap[""]->fieldMap[fullName];
323 }
324 else {
325 return this->collectMap[""]->fieldMap[collectfield];
326 }
327}
328
329text_t oaiconfig::getBaseURL()
330{
331 return this->baseURL;
332}
333text_t oaiconfig::getBaseLibraryURL()
334{
335 return this->baseLibraryURL;
336}
337text_t oaiconfig::getBaseDocRoot()
338{
339 return this->baseDocRoot;
340}
341text_t oaiconfig::getRepositoryName()
342{
343 return this->repositoryName;
344}
345text_t oaiconfig::getRepositoryId()
346{
347 return this->repositoryId;
348}
349text_t oaiconfig::getRepositoryIdVersion()
350{
351 return this->repositoryIdVersion;
352}
353text_t oaiconfig::getMaintainer()
354{
355 return this->maintainer;
356}
357text_t oaiconfig::getSetName(const text_t &setSpec)
358{
359 if (this->collectMap[setSpec] == NULL) {
360 return "" ;
361 }
362
363 return this->collectMap[setSpec]->setName;
364
365}
366
367text_t oaiconfig::getSetDescription(const text_t &setSpec)
368{
369 if (this->collectMap[setSpec] == NULL) {
370 return "" ;
371 }
372
373 return this->collectMap[setSpec]->setDescription;
374}
375
Note: See TracBrowser for help on using the repository browser.