#include "oaiconfig.h" #include #include #include "fileutil.h" /** * The mapping works as follows in the oai.cfg or collect.cfg file. * * A line is in the format oaimapping * * The map here is used to look up the "Greenstone" name which is mapped from * a given OAI field name, the reverse direction to that given in the * Greenstone collect.cfg file. The oairecordaction class instance which * produces output for an OAI record information request thus uses the map * to work from the field in the collection it has on hand which OAI * record name it should use instead. * * An extension is to be used for this in which the OAI field name in the * collect.cfg file can be made specific for a particular record format. * This is done using the OAI field name in the format of * . * Thus, an rfc1807 Title field would be referred to as rfc1807.Title * * A collection-level mapping can be provided in oai.cfg by prepending * collname to collection field: * * In the absence of a particular format name, the mapping is taken to be * universal. */ oaiconfig::oaiconfig() : configurable () { this->resumptionSize = -1; // Default = do not use resumption tokens } oaiconfig::oaiconfig(text_t &gsdlhome, text_t &gsdlcollect) { // read main configuration file (oai.cfg) to get oai collections text_t mainconfig = filename_cat(gsdlhome, "etc", "oai.cfg"); this->collection = ""; this->resumptionSize = -1; this->read_configfile(mainconfig); // then if we've not got a specified collection in the gsdlcollect // parameter, read in all the collection's individual configurations if (gsdlcollect == "") { text_tarray::iterator start = this->collectList.begin(); text_tarray::iterator here = this->collectList.end()-1; while (here != start) { if (!this->configureCollection(gsdlhome, *here)) { this->collectList.erase(here); } --here; } // and do the first one if (!this->configureCollection(gsdlhome, *here)) { this->collectList.erase(here); } } else { // what do we do if this fails? this->configureCollection(gsdlhome, gsdlcollect); } } oaiconfig::~oaiconfig() { oaicollectmap::iterator here = this->collectMap.begin(); oaicollectmap::iterator end = this->collectMap.end(); while (here != end) { delete here->second; ++here; } } int oaiconfig::resumeAfter() { return this->resumptionSize; } int oaiconfig::getOAIVersion() { if (this->oaiVersion == "1.1") { return 110; } return 200; } bool oaiconfig::configureCollection(const text_t &gsdlhome, const text_t &gsdlcollect) { text_t cnfgfile = filename_cat(gsdlhome, "collect", gsdlcollect, "etc", "collect.cfg"); if (!file_exists(cnfgfile)) { return false; } this->collection = gsdlcollect; this->read_configfile(cnfgfile); return true; } void oaiconfig::configure (const text_t &key, const text_tarray &cfgline) { // we've got an oai mapping item, and at least two fields if (key == "oaimapping" && cfgline.size() > 1) { text_t::const_iterator colonAt; text_t index, name, configCollection; // Take a default collection as being whatever the collection being configured is... configCollection = this->collection; // get the name of the (collection) field to map; this may actually // be in a colon separated format of the type // : index = cfgline[0]; if ((colonAt = findchar(index.begin(), index.end(), ':')) != index.end()) { configCollection = substr(index.begin(), colonAt); if (this->collection != "" && configCollection != this->collection) { cerr << "Attempt to configure OAI mappings for " << configCollection << " in " << this->collection << endl; } colonAt += 1; index = substr(colonAt, index.end()); } // the second parameter is the metadata field to map the collection // field onto. It may be provided with a metadata protocol (which // will be given first and separated by a period or full stop). In // the case of format.field name, the splitting is done here. if ((colonAt = findchar(cfgline[1].begin(), cfgline[1].end(), '.')) != cfgline[1].end()) { text_t stub = substr(cfgline[1].begin(), colonAt); colonAt += 1; name = substr(colonAt, cfgline[1].end()); index.append(":"); index.append(stub); } else { name = cfgline[1]; } // now 'index' is in the form :(formatname) // 'name' is simply the fieldname within the format // 'configCollection' is the collection to be configured // now simply map the field name (index) onto the collection name (name) if (this->collectMap[configCollection] == NULL) { this->collectMap[configCollection] = new oaicollectconfig(configCollection); } this->collectMap[configCollection]->fieldMap[index] = name; // cerr << "Mapping " << index << " to " << name << " in " << configCollection << endl; // TODO: check that the mapped field is actually in use } else if (key == "oaicollection" && cfgline.size() >= 1) { // Configure a collection to be used as part of the OAI archive. // This line should read: // // oaicollection // // Where is the name of the directory inside the // gsdl/collect folder which contains the collection. // // To configure several collections, merely repeat this line, // or alternatively use additional collection names after the // first one. // // This configuration should only appear in oai.cfg // if (this->collection != "") { cerr << "Attempt to configure an oai collection outside of oai.cfg" << endl; cerr << "Configuration attempted in " << this->collection << " collection." << endl; exit(1); } for (int c = 0; c < cfgline.size(); ++c) { this->collectList.push_back(cfgline[c]); } } else if (key == "oaimetadata" && cfgline.size() >= 1) { // List of metadata prefixes to suuport // This line should read: // // oaicollection ... // // // This configuration should only appear in oai.cfg // if (this->collection != "") { cerr << "Attempt to configure oai metadata outside of oai.cfg" << endl; cerr << "Configuration attempted in " << this->collection << " collection." << endl; exit(1); } for (int c = 0; c < cfgline.size(); ++c) { // todo: check that the set name is valid this->metadataSet.insert(cfgline[c]); } } else if (key == "oaiinfo" && cfgline.size() >= 1) { // Get a piece of information for the oai repository information // request. The line should read: // // oaiinfo // // This configuration should only be attempted in oai.cfg // if (this->collection != "") { cerr << "Attempt to set oai information outside of oai.cfg" << endl; cerr << "Configuration attempted in " << this->collection << " collection." << endl; exit(1); } // if no second parameter is given, then the first parameter if (cfgline.size() == 1) { this->infoMap[cfgline[0]] = cfgline[0]; } else { this->infoMap[cfgline[0]] = cfgline[1]; } } else if ( key == "oaisetname" || key == "oaisetdescription") { text_t coll_name; text_t value = ""; if (this->collection != "") { // we are in collect.cfg coll_name = this->collection; if (cfgline.size() == 1) { // just the collection value value = cfgline[0]; } else if (cfgline.size() == 2) { // we have a subset name (eg for classifier) coll_name.append(":"); coll_name.append(cfgline[0]); value = cfgline[1]; } } else if (cfgline.size() == 2) { // oai.cfg, line should be collname, setName coll_name = cfgline[0]; value = cfgline[1]; } if (value != "") { if (this->collectMap[coll_name] == NULL) { this->collectMap[coll_name] = new oaicollectconfig(coll_name); } if (key == "oaisetname") { this->collectMap[coll_name]->setName = value; } else if (key == "oaisetdescription") { this->collectMap[coll_name]->setDescription = value; } } } else if (key == "resumeafter" && cfgline.size() >= 1) { this->resumptionSize = cfgline[0].getint(); } else if (key == "maintainer") { this->maintainer = cfgline[0]; } else if (key == "repositoryName") { this->repositoryName = cfgline[0]; } else if (key == "baseURL") { this->baseURL = cfgline[0]; } else if (key == "baseLibraryURL") { this->baseLibraryURL = cfgline[0]; } else if (key == "baseDocRoot") { this->baseDocRoot = cfgline[0]; } } text_t oaiconfig::getMapping(const text_t &collection, const text_t &collectfield) { if (this->collectMap[collection] == NULL) { return ""; } return this->collectMap[collection]->fieldMap[collectfield]; } /** * Get the mapping for a field in a given collection; if no mapping * exists, the result will be a blank string. */ text_t oaiconfig::getMapping(const text_t &collection, const text_t &collectfield, const text_t &formatname) { text_t fullName = collectfield; fullName.append(":"); fullName.append(formatname); // try the collection-specific options first if (this->collectMap[collection] != NULL) { // first try the most specific item - this collection, and given that protocol if (this->collectMap[collection]->fieldMap.count(fullName) >= 1) { return this->collectMap[collection]->fieldMap[fullName]; } // otherwise, fall back to this collection, and all protocols else if (this->collectMap[collection]->fieldMap.count(collectfield) >= 1) { return this->collectMap[collection]->fieldMap[collectfield]; } } // if no mappings exist, return an empty item if (this->collectMap[""] == NULL) { return ""; } // then try generic rules if (this->collectMap[""]->fieldMap.count(fullName) >= 1) { return this->collectMap[""]->fieldMap[fullName]; } else { return this->collectMap[""]->fieldMap[collectfield]; } } text_t oaiconfig::getBaseURL() { return this->baseURL; } text_t oaiconfig::getBaseLibraryURL() { return this->baseLibraryURL; } text_t oaiconfig::getBaseDocRoot() { return this->baseDocRoot; } text_t oaiconfig::getRepositoryName() { return this->repositoryName; } text_t oaiconfig::getMaintainer() { return this->maintainer; } text_t oaiconfig::getSetName(const text_t &setSpec) { if (this->collectMap[setSpec] == NULL) { return "" ; } return this->collectMap[setSpec]->setName; } text_t oaiconfig::getSetDescription(const text_t &setSpec) { if (this->collectMap[setSpec] == NULL) { return "" ; } return this->collectMap[setSpec]->setDescription; }