/* * IIIFPMH.java * Copyright (C) 2019 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.IIIFXML; //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.HashSet; import java.util.Map.Entry; import org.apache.log4j.Logger; /** Implements the IIIF service for GS3 collections. * Digs into each collection's database to study the metadata * and from that determine what file in a document's assocdir * can be used to provide a source image for the doc * */ public class IIIFPMH extends ServiceRack { static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.IIIFPMH.class.getName()); protected SimpleCollectionDatabase coll_db = null; protected String site_name = ""; protected String coll_name = ""; // set this up during configure protected Element list_sets_response = null; protected Element meta_formats_definition = null; protected HashMap> format_elements_map = null; protected HashMap format_meta_elem_map = null; protected String index_stem = ""; protected String infodb_type = ""; /** constructor */ public IIIFPMH() { } public void cleanUp() { super.cleanUp();//?? if(this.coll_db != null) { this.coll_db.closeDatabase(); this.coll_db = null; } } /** configure this service info is the IIIFPMH 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 IIIFPMH(extends ServiceRack) 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 IIIFPMH..."); 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); // Is indexStem needed for IIIF // **** 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) { this.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) { this.infodb_type = GSXML.getNodeText(infodb_type_elem); } } if (index_stem == null || index_stem.equals("")) { this.index_stem = this.cluster_name; // index_stem is the name of the db in indext/text, it is . } if (infodb_type == null || infodb_type.equals("")) { this.infodb_type = "gdbm"; // the default } Element get_record = this.desc_doc.createElement(GSXML.SERVICE_ELEM); get_record.setAttribute(GSXML.NAME_ATT, IIIFXML.GET_RECORD); get_record.setAttribute(GSXML.TYPE_ATT, "iiif"); this.short_service_info.appendChild(get_record); return true; } public boolean configureIIIF(Element iiif_config_elem) { // Open the coll db db databases and store handles to them coll_db = new SimpleCollectionDatabase(infodb_type); if (!coll_db.databaseOK()) { logger.error("Couldn't create the collection database of type "+infodb_type); return false; } // Open databases 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; } return true; } /** returns a specific service description */ public Element getServiceDescription(Document doc, String service_id, String lang, String subset) { if (service_id.equals(IIIFXML.GET_RECORD)) { Element get_record = doc.createElement(GSXML.SERVICE_ELEM); get_record.setAttribute(GSXML.NAME_ATT, IIIFXML.GET_RECORD); get_record.setAttribute(GSXML.TYPE_ATT, "iiif"); return get_record; } return null; } /** returns the actual record element used in the IIIF GetRecord response */ protected Element processGetRecord(Element req) { /** arguments: identifier: required * Exceptions: badArgument; cannotDisseminateFormat; idDoesNotExist */ NodeList params = GSXML.getChildrenByTagName(req, GSXML.PARAM_ELEM); HashMap param_map = GSXML.getParamMap(params); Document doc = XMLConverter.newDOM(); String oid = param_map.get(IIIFXML.OID); // TODO should this be identifier??? // 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 collection index database."); return IIIFXML.createErrorResponse(IIIFXML.ID_DOES_NOT_EXIST, ""); } // **** Element get_record_response = doc.createElement(GSXML.RESPONSE_ELEM); Element get_record = doc.createElement(IIIFXML.GET_RECORD); get_record_response.appendChild(get_record); Element record = doc.createElement(IIIFXML.RECORD); //compose the header element record.appendChild(createHeaderElement(doc, oid)); //compose the metadata element record.appendChild(createMetadataElement(doc, info)); get_record.appendChild(record); return get_record_response; } /** create the metadata element used when processing GetRecord request */ protected Element createMetadataElement(Document doc, DBInfo info) { // the element Element metadata_message = doc.createElement(IIIFXML.METADATA); // the element //Element prfx_str_elem = (Element)doc.importNode(this.format_meta_elem_map.get(prefix), true); //metadata.appendChild(prfx_str_elem); //Element meta_format_element = GSXML.getNamedElement(this.meta_formats_definition, OAIXML.METADATA_FORMAT, GSXML.NAME_ATT, prefix); //NodeList elements = meta_format_element.getElementsByTagName(OAIXML.ELEMENT); // for each element in the definition addFirstMetadata(metadata_message, "assocfilepath", info); addFirstMetadata(metadata_message, "Image", info); /* Set keys = info.getKeys(); if (keys != null && keys.size()!=0) { for (String metaname: keys) { addMetadata(metadata_message, metaname, info); } } */ /* for (int i=0; i values = info.getMultiInfo(meta_name); if (values != null && values.size()>0) { addMetadataElement(meta_list_elem, meta_name, values.get(0)); } } /** more complicated addMetadata - can add multiple items. */ /* protected void addMetadata(Element meta_list_elem, String new_meta_name, String select_type, String name_list, DBInfo info) { String[] names = name_list.split(","); for (int i=0; i values; // some special words if (names[i].startsWith(OAIXML.GSF_LINK_PREFIX)) { values = new Vector(); String base_url = OAIXML.getBaseURL(); // e.g. e.g. http://host:port/greenstone3/oaiserver String link_url = null; if (names[i].equals(OAIXML.GSF_LINK_PREFIX+OAIXML.LINK_TYPE_DOCUMENT)) { link_url = base_url.replace("oaiserver", "library") + "/collection/" + this.coll_name + "/document/" + info.getInfo("Identifier"); } else if (names[i].equals(OAIXML.GSF_LINK_PREFIX+OAIXML.LINK_TYPE_SOURCE)) { String srcfile = info.getInfo("srclinkFile"); if (!srcfile.equals("")) { link_url = base_url.replace("oaiserver", "") + "sites/" + this.site_name + "/collect/" + this.coll_name + "/index/assoc/" + info.getInfo("assocfilepath") + "/" + srcfile; } } if (link_url !=null) { values.add(link_url); } } else { values = info.getMultiInfo(names[i]); } if (values == null || values.size()==0) { continue; } for (int j=0; j