/* * OAIPMH.java * Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.greenstone.gsdl3.service; // Greenstone classes import org.greenstone.gsdl3.core.GSException; import org.greenstone.gsdl3.util.GSXML; import org.greenstone.gsdl3.util.OAIXML; import org.greenstone.gsdl3.util.OID; import org.greenstone.gsdl3.util.GSFile; import org.greenstone.gsdl3.util.XMLConverter; import org.greenstone.gsdl3.util.SimpleCollectionDatabase; import org.greenstone.gsdl3.util.DBInfo; // XML classes import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; // General Java classes import java.io.File; import java.util.StringTokenizer; import java.util.Vector; import java.util.Set; import java.util.Iterator; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Map.Entry; import org.apache.log4j.Logger; /** Implements the oai metadata retrieval service for GS3 collections. * Dig into each collection's database and retrieve the metadata * * @author Xiao */ public class OAIPMH extends ServiceRack { static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.OAIPMH.class.getName()); protected SimpleCollectionDatabase coll_db = null; protected String site_name = ""; protected String coll_name = ""; /** constructor */ public OAIPMH() { } public void cleanUp() { super.cleanUp();//?? this.coll_db.closeDatabase(); } /** configure this service info is the OAIPMH service rack from collectionConfig.xml, and extra_info is buildConfig.xml */ public boolean configure(Element info, Element extra_info) { if (!super.configure(info, extra_info)){ logger.info("Configuring ServiceRack.java returns false."); return false; } //get the names from ServiceRack.java this.site_name = this.router.getSiteName(); this.coll_name = this.cluster_name; logger.info("Configuring OAIPMH..."); this.config_info = info; // the index stem is either specified in the buildConfig.xml file (extra_info) or uses the collection name Element metadata_list = (Element) GSXML.getChildByTagName(extra_info, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER); String index_stem = ""; String infodb_type = ""; if (metadata_list != null) { Element index_stem_elem = (Element) GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "indexStem"); if (index_stem_elem != null) { index_stem = GSXML.getNodeText(index_stem_elem); } Element infodb_type_elem = (Element) GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "infodbType"); if (infodb_type_elem != null) { infodb_type = GSXML.getNodeText(infodb_type_elem); } } if (index_stem == null || index_stem.equals("")) { index_stem = this.cluster_name; } if (infodb_type == null || infodb_type.equals("")) { infodb_type = "gdbm"; // the default } coll_db = new SimpleCollectionDatabase(infodb_type); if (coll_db == null) { logger.error("Couldn't create the collection database of type "+infodb_type); return false; } // Open database for querying String coll_db_file = GSFile.collectionDatabaseFile(this.site_home, this.cluster_name, index_stem, infodb_type); if (!this.coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ)) { logger.error("Could not open collection database!"); return false; } // the short_service_info is used by the message router to find the method names, //so we just use the doc variable in class ServiceRack to create the xml; but // in each method we will use OAIXML to create the response xml // set up short_service_info_ - just the name Element identify = this.doc.createElement(OAIXML.SERVICE); identify.setAttribute(OAIXML.NAME, OAIXML.IDENTIFY); identify.setAttribute(GSXML.TYPE_ATT, "oai"); this.short_service_info.appendChild(identify); Element list_records = this.doc.createElement(OAIXML.SERVICE); list_records.setAttribute(OAIXML.NAME, OAIXML.LIST_RECORDS); list_records.setAttribute(GSXML.TYPE_ATT, "oai"); this.short_service_info.appendChild(list_records); Element list_identifiers = this.doc.createElement(OAIXML.SERVICE); list_identifiers.setAttribute(OAIXML.NAME, OAIXML.LIST_IDENTIFIERS); list_identifiers.setAttribute(GSXML.TYPE_ATT, "oai"); this.short_service_info.appendChild(list_identifiers); Element list_sets = this.doc.createElement(OAIXML.SERVICE); list_sets.setAttribute(OAIXML.NAME, OAIXML.LIST_SETS); list_sets.setAttribute(GSXML.TYPE_ATT, "oai"); this.short_service_info.appendChild(list_sets); Element list_metadata_formats = this.doc.createElement(OAIXML.SERVICE); list_metadata_formats.setAttribute(OAIXML.NAME, OAIXML.LIST_METADATA_FORMATS); list_metadata_formats.setAttribute(GSXML.TYPE_ATT, "oai"); this.short_service_info.appendChild(list_metadata_formats); Element get_record = this.doc.createElement(OAIXML.SERVICE); get_record.setAttribute(OAIXML.NAME, OAIXML.GET_RECORD); get_record.setAttribute(GSXML.TYPE_ATT, "oai"); this.short_service_info.appendChild(get_record); return true; } /** returns a specific service description */ public Element getServiceDescription(String service_id, String lang, String subset) { if (service_id.equals(OAIXML.IDENTIFY)) { Element identify = this.doc.createElement(OAIXML.SERVICE); identify.setAttribute(OAIXML.NAME, OAIXML.IDENTIFY); identify.setAttribute(GSXML.TYPE_ATT, "oai"); return identify; } if (service_id.equals(OAIXML.LIST_RECORDS)) { Element list_records = this.doc.createElement(OAIXML.SERVICE); list_records.setAttribute(OAIXML.NAME, OAIXML.LIST_RECORDS); list_records.setAttribute(GSXML.TYPE_ATT, "oai"); return list_records; } if (service_id.equals(OAIXML.LIST_IDENTIFIERS)) { Element list_identifiers = this.doc.createElement(OAIXML.SERVICE); list_identifiers.setAttribute(OAIXML.NAME, OAIXML.LIST_IDENTIFIERS); list_identifiers.setAttribute(GSXML.TYPE_ATT, "oai"); return list_identifiers; } if (service_id.equals(OAIXML.LIST_SETS)) { Element list_sets = this.doc.createElement(OAIXML.SERVICE); list_sets.setAttribute(OAIXML.NAME, OAIXML.LIST_SETS); list_sets.setAttribute(GSXML.TYPE_ATT, "oai"); return list_sets; } if (service_id.equals(OAIXML.LIST_METADATA_FORMATS)) { Element list_metadata_formats = this.doc.createElement(OAIXML.SERVICE); list_metadata_formats.setAttribute(OAIXML.NAME, OAIXML.LIST_METADATA_FORMATS); list_metadata_formats.setAttribute(GSXML.TYPE_ATT, "oai"); return list_metadata_formats; } if (service_id.equals(OAIXML.GET_RECORD)) { Element get_record = this.doc.createElement(OAIXML.SERVICE); get_record.setAttribute(OAIXML.NAME, OAIXML.GET_RECORD); get_record.setAttribute(GSXML.TYPE_ATT, "oai"); return get_record; } return null; } /** return the metadata information about this set of the repository */ protected Element processIdentify(Element req) { return null; } /** return the metadata information */ protected Element processListSets(Element req) { //This method is never called unless each set in the returned message contain a //'description' element so that we need to ask each collection for their info return null; } /** return the metadata information */ protected Element processGetRecord(Element req) { /** arguments: identifier: required metadataPrefix: required * Exceptions: badArgument; cannotDisseminateFormat; idDoesNotExist */ NodeList params = GSXML.getChildrenByTagName(req, OAIXML.PARAM); HashMap param_map = OAIXML.getParamMap(params); String prefix = (String)param_map.get(OAIXML.METADATA_PREFIX); if (prefix == null || prefix.equals("")) { //Just a double-check logger.error("the value of metadataPrefix att is not present in the request."); return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, "")); } Element metadata_format = getMetadataFormatElement(prefix); if(metadata_format == null) { logger.error("metadata prefix is not supported."); return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, "")); } String oid = (String)param_map.get(OAIXML.OID); //get a DBInfo object of the identifier; if this identifier is not present in the database, // null is returned. DBInfo info = this.coll_db.getInfo(oid); if (info == null) { logger.error("OID: " + oid + " is not present in the database."); return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.ID_DOES_NOT_EXIST, "")); } ArrayList keys = new ArrayList(info.getKeys()); String lastmodified = ""; if(keys.contains(OAIXML.LASTMODIFIED)) { lastmodified = info.getInfo(OAIXML.LASTMODIFIED); } lastmodified = OAIXML.getTime(Long.parseLong(lastmodified)); Element get_record = OAIXML.createElement(OAIXML.GET_RECORD); Element record = OAIXML.createElement(OAIXML.RECORD); //compose the header element record.appendChild(createHeaderElement(oid, lastmodified)); //compose the metadata element record.appendChild(createMetadataElement(prefix, info, metadata_format)); get_record.appendChild(record); return OAIXML.getResponse(get_record); } /** return a list of identifiers */ protected Element processListIdentifiers(Element req) { /** arguments: metadataPrefix: required * from: optional * until: optional * set: optional * resumptionToken: exclusive and optional (ignored as it has been handled by OAIReceptionist) * Exceptions: badArgument; cannotDisseminateFormat; idDoesNotExist */ NodeList params = GSXML.getChildrenByTagName(req, OAIXML.PARAM); if(params.getLength() == 0) { logger.error("must at least have the metadataPrefix parameter, can't be none"); return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.BAD_ARGUMENT, "")); } HashMap param_map = OAIXML.getParamMap(params); String prefix = ""; Date from_date = null; Date until_date = null; if(param_map.containsKey(OAIXML.METADATA_PREFIX) == false) { //Just a double-check logger.error("A param element containing the metadataPrefix is not present."); return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, "")); } prefix = (String)param_map.get(OAIXML.METADATA_PREFIX); if (prefix == null || prefix.equals("")) { //Just a double-check logger.error("the value of metadataPrefix att is not present in the request."); return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, "")); } if(param_map.containsKey(OAIXML.FROM)) { String from = (String)param_map.get(OAIXML.FROM); from_date = OAIXML.getDate(from); } if(param_map.containsKey(OAIXML.UNTIL)) { String until = (String)param_map.get(OAIXML.UNTIL); until_date = OAIXML.getDate(until); } Element metadata_format = getMetadataFormatElement(prefix); if(metadata_format == null) { logger.error("metadata prefix is not supported."); return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, "")); } ArrayList oid_list = getChildrenIds(OAIXML.BROWSELIST); if (oid_list == null) { logger.error("No matched records found in collection: browselist is empty"); return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.NO_RECORDS_MATCH, "")); } // all validation is done Element list_identifiers = OAIXML.createElement(OAIXML.LIST_IDENTIFIERS); for(int i=0; i element //OAIXML.oai_version is read from OAIConfig.xml and its default value is "2.0" Element metadata = OAIXML.createElement(OAIXML.METADATA); Element prfx_str_elem = OAIXML.getMetadataPrefixElement(prfx_str, OAIXML.oai_version); metadata.appendChild(prfx_str_elem); String[] metadata_names = getMetadataNameMapping(metadata_format); HashMap meta_map = getInfoByNames(info, metadata_names); if (meta_map == null) { return metadata; } ArrayList meta_list = new ArrayList(meta_map.entrySet()); for (int j=0; j,, in which the mapped name is * optional. The mapped name is looked up in the DBInfo; if not present, use the first * name which is mendatory. */ protected boolean containsMetadata(DBInfo info, String[] metadata_names) { if (metadata_names == null) return false; logger.info("checking metadata names in db."); for(int i=0; i: *---------------------------------------------------------------------- [HASH01a84acb0f1aad2380493b3a] doc 1 en windows_1252 HTMLPlug 205093 wb34te.htm 1 World Bank Development in practice: Toward Gender Equality (wb34te) English A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-Z Women, gender and development, women's organizations achieve gender equality http://wb34te/wb34te.htm Development in practice: Toward Gender Equality <lastmodified>1178245194 <assocfilepath>HASH01a8.dir <memberof>CL3 <archivedir>HASH01a8.dir <thistype>VList <childtype>VList <contains>".1;".2;".3;".4;".5;".6;".7;".8;".9 <docnum>349 ---------------------------------------------------------------------- */ public String[] getMetadata(DBInfo info, String names) { String[] name_value = new String[2]; ArrayList keys = new ArrayList(info.getKeys()); for (int i=0; i<keys.size(); i++) { String key = (String)keys.get(i); String first_name = ""; String second_name = ""; int index = names.indexOf(","); if(index != -1) { first_name = names.substring(0, index); second_name = names.substring(index + 1); } else { first_name = second_name = names; } if(key.equals(second_name)) { String meta_value = info.getInfo(key); name_value[0] = first_name; name_value[1] = meta_value; return name_value; } } return null; } protected HashMap getInfoByNames(DBInfo info, String[] metadata_names) { if (metadata_names == null) { return null; } HashMap map = new HashMap(); boolean empty_map = true; for(int i=0; i<metadata_names.length; i++) { String[] name_value = getMetadata(info, metadata_names[i]); if(name_value != null) { map.put(name_value[0], name_value[1]); empty_map = false; } } return (empty_map == true) ? null : map; } }