/*
* 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