source: gs3-extensions/iiif-servlet/trunk/src/gsdl-src/java/org/greenstone/gsdl3/service/IIIFPMH.java@ 32874

Last change on this file since 32874 was 32874, checked in by davidb, 5 years ago

Next round of changes, migrating from OAI imprint to what is needed for IIIF

File size: 11.5 KB
Line 
1/*
2 * IIIFPMH.java
3 * Copyright (C) 2019 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.service;
20
21// Greenstone classes
22import org.greenstone.gsdl3.core.GSException;
23import org.greenstone.gsdl3.util.GSXML;
24import org.greenstone.gsdl3.util.IIIFXML;
25//import org.greenstone.gsdl3.util.OAIXML; // ****
26import org.greenstone.gsdl3.util.OID;
27import org.greenstone.gsdl3.util.GSFile;
28import org.greenstone.gsdl3.util.XMLConverter;
29
30import org.greenstone.gsdl3.util.SimpleCollectionDatabase;
31import org.greenstone.gsdl3.util.DBInfo;
32// XML classes
33import org.w3c.dom.Document;
34import org.w3c.dom.Element;
35import org.w3c.dom.NodeList;
36
37// General Java classes
38import java.io.File;
39import java.util.StringTokenizer;
40import java.util.Vector;
41import java.util.Set;
42import java.util.Iterator;
43import java.util.ArrayList;
44import java.util.Date;
45import java.util.HashMap;
46import java.util.HashSet;
47import java.util.Map.Entry;
48
49import org.apache.log4j.Logger;
50
51/** Implements the IIIF service for GS3 collections.
52 * Digs into each collection's database to study the metadata
53 * and from that determine what file in a document's assocdir
54 * can be used to provide a source image for the doc
55 *
56 */
57
58public class IIIFPMH extends ServiceRack {
59
60 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.IIIFPMH.class.getName());
61
62 protected SimpleCollectionDatabase coll_db = null;
63
64 protected String site_name = "";
65 protected String coll_name = "";
66
67 // set this up during configure
68 protected Element list_sets_response = null;
69
70 protected Element meta_formats_definition = null;
71 protected HashMap<String, HashSet<String>> format_elements_map = null;
72 protected HashMap<String, Element> format_meta_elem_map = null;
73
74 protected String index_stem = "";
75 protected String infodb_type = "";
76
77 /** constructor */
78 public IIIFPMH() {
79 }
80
81 public void cleanUp() {
82 super.cleanUp();//??
83
84 if(this.coll_db != null) {
85 this.coll_db.closeDatabase();
86 this.coll_db = null;
87 }
88 }
89
90 /** configure this service
91 info is the IIIFPMH service rack from collectionConfig.xml, and
92 extra_info is buildConfig.xml */
93 public boolean configure(Element info, Element extra_info) {
94 if (!super.configure(info, extra_info)){
95 logger.info("Configuring IIIFPMH(extends ServiceRack) returns false.");
96 return false;
97 }
98
99 //get the names from ServiceRack.java
100 this.site_name = this.router.getSiteName();
101 this.coll_name = this.cluster_name;
102
103 logger.info("Configuring IIIFPMH...");
104
105 this.config_info = info;
106
107 // the index stem is either specified in the buildConfig.xml file (extra_info) or uses the collection name
108 Element metadata_list = (Element) GSXML.getChildByTagName(extra_info, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
109
110 // Is indexStem needed for IIIF // ****
111 if (metadata_list != null) {
112
113 Element index_stem_elem = (Element) GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "indexStem");
114
115 if (index_stem_elem != null) {
116 this.index_stem = GSXML.getNodeText(index_stem_elem);
117 }
118
119 Element infodb_type_elem = (Element) GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "infodbType");
120 if (infodb_type_elem != null) {
121 this.infodb_type = GSXML.getNodeText(infodb_type_elem);
122 }
123
124 }
125
126 if (index_stem == null || index_stem.equals("")) {
127 this.index_stem = this.cluster_name; // index_stem is the name of the db in indext/text, it is <colname>.<db>
128 }
129 if (infodb_type == null || infodb_type.equals("")) {
130 this.infodb_type = "gdbm"; // the default
131 }
132
133 Element get_record = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
134 get_record.setAttribute(GSXML.NAME_ATT, IIIFXML.GET_RECORD);
135 get_record.setAttribute(GSXML.TYPE_ATT, "iiif");
136 this.short_service_info.appendChild(get_record);
137
138 return true;
139 }
140
141 public boolean configureIIIF(Element iiif_config_elem) {
142
143 // Open the coll db db databases and store handles to them
144 coll_db = new SimpleCollectionDatabase(infodb_type);
145 if (!coll_db.databaseOK()) {
146 logger.error("Couldn't create the collection database of type "+infodb_type);
147 return false;
148 }
149
150 // Open databases for querying
151 String coll_db_file = GSFile.collectionDatabaseFile(this.site_home, this.cluster_name, index_stem, infodb_type);
152 if (!this.coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ)) {
153 logger.error("Could not open collection database!");
154 return false;
155 }
156
157 return true;
158 }
159
160 /** returns a specific service description */
161 public Element getServiceDescription(Document doc, String service_id, String lang, String subset) {
162
163 if (service_id.equals(IIIFXML.GET_RECORD)) {
164 Element get_record = doc.createElement(GSXML.SERVICE_ELEM);
165 get_record.setAttribute(GSXML.NAME_ATT, IIIFXML.GET_RECORD);
166 get_record.setAttribute(GSXML.TYPE_ATT, "iiif");
167 return get_record;
168 }
169
170 return null;
171 }
172
173 /** returns the actual record element used in the IIIF GetRecord response */
174 protected Element processGetRecord(Element req) {
175 /** arguments:
176 identifier: required
177 * Exceptions: badArgument; cannotDisseminateFormat; idDoesNotExist
178 */
179 NodeList params = GSXML.getChildrenByTagName(req, GSXML.PARAM_ELEM);
180 HashMap<String, String> param_map = GSXML.getParamMap(params);
181
182 Document doc = XMLConverter.newDOM();
183
184 String oid = param_map.get(IIIFXML.OID); // TODO should this be identifier???
185
186 // Get a DBInfo object of the identifier; if this identifier is not present in the database,
187 // null is returned.
188 DBInfo info = this.coll_db.getInfo(oid);
189 if (info == null) {
190 logger.error("OID: " + oid + " is not present in the collection index database.");
191 return IIIFXML.createErrorResponse(IIIFXML.ID_DOES_NOT_EXIST, "");
192 }
193
194
195 // ****
196 Element get_record_response = doc.createElement(GSXML.RESPONSE_ELEM);
197 Element get_record = doc.createElement(IIIFXML.GET_RECORD);
198 get_record_response.appendChild(get_record);
199 Element record = doc.createElement(IIIFXML.RECORD);
200 //compose the header element
201 record.appendChild(createHeaderElement(doc, oid));
202 //compose the metadata element
203 record.appendChild(createMetadataElement(doc, info));
204 get_record.appendChild(record);
205 return get_record_response;
206 }
207
208
209 /** create the metadata element used when processing GetRecord request
210 */
211
212 protected Element createMetadataElement(Document doc, DBInfo info) {
213 // the <metadata> element
214 Element metadata_message = doc.createElement(IIIFXML.METADATA);
215
216 // the <oai:dc namespace...> element
217 //Element prfx_str_elem = (Element)doc.importNode(this.format_meta_elem_map.get(prefix), true);
218 //metadata.appendChild(prfx_str_elem);
219
220 //Element meta_format_element = GSXML.getNamedElement(this.meta_formats_definition, OAIXML.METADATA_FORMAT, GSXML.NAME_ATT, prefix);
221 //NodeList elements = meta_format_element.getElementsByTagName(OAIXML.ELEMENT);
222 // for each element in the definition
223
224 addFirstMetadata(metadata_message, "assocfilepath", info);
225 addFirstMetadata(metadata_message, "Image", info);
226
227 /*
228 Set<String> keys = info.getKeys();
229 if (keys != null && keys.size()!=0) {
230 for (String metaname: keys) {
231 addMetadata(metadata_message, metaname, info);
232 }
233 }
234 */
235
236 /*
237 for (int i=0; i<elements.getLength(); i++) {
238 Element e = (Element)elements.item(i);
239
240 // look up the element name
241 //addMetadata(prfx_str_elem, e.getAttribute(GSXML.NAME_ATT), info);
242 addMetadata(metadata, e.getAttribute(GSXML.NAME_ATT), info);
243 }
244 */
245
246 // output any metadata that is not just a simple mapping
247 //addCustomMetadata(prfx_str_elem, prefix, info); // ****
248 return metadata_message;
249 }
250
251 /** a simple addMetadata where we look for meta_name metadata, and add as that name*/
252
253
254 protected void addFirstMetadata(Element meta_list_elem, String meta_name, DBInfo info) {
255 Vector<String> values = info.getMultiInfo(meta_name);
256 if (values != null && values.size()>0) {
257 addMetadataElement(meta_list_elem, meta_name, values.get(0));
258
259 }
260 }
261
262
263 /** more complicated addMetadata - can add multiple items. */
264 /*
265 protected void addMetadata(Element meta_list_elem, String new_meta_name, String select_type, String name_list, DBInfo info) {
266 String[] names = name_list.split(",");
267 for (int i=0; i<names.length; i++) {
268 Vector<String> values;
269 // some special words
270 if (names[i].startsWith(OAIXML.GSF_LINK_PREFIX)) {
271 values = new Vector<String>();
272 String base_url = OAIXML.getBaseURL(); // e.g. e.g. http://host:port/greenstone3/oaiserver
273 String link_url = null;
274 if (names[i].equals(OAIXML.GSF_LINK_PREFIX+OAIXML.LINK_TYPE_DOCUMENT)) {
275 link_url = base_url.replace("oaiserver", "library") + "/collection/" + this.coll_name + "/document/" + info.getInfo("Identifier");
276 } else if (names[i].equals(OAIXML.GSF_LINK_PREFIX+OAIXML.LINK_TYPE_SOURCE)) {
277 String srcfile = info.getInfo("srclinkFile");
278 if (!srcfile.equals("")) {
279 link_url = base_url.replace("oaiserver", "") + "sites/"
280 + this.site_name
281 + "/collect/" + this.coll_name + "/index/assoc/"
282 + info.getInfo("assocfilepath") + "/" + srcfile;
283 }
284 }
285 if (link_url !=null) {
286 values.add(link_url);
287 }
288 } else {
289 values = info.getMultiInfo(names[i]);
290 }
291 if (values == null || values.size()==0) {
292 continue;
293 }
294 for (int j=0; j<values.size(); j++) {
295 addMetadataElement(meta_list_elem, new_meta_name, values.get(j));
296 if (select_type.equals(OAIXML.SELECT_SINGLE_VALUE)) {
297 return; // only want to add one value
298 }
299 }
300 if (select_type.equals(OAIXML.SELECT_FIRST_VALID_META)) {
301 return; // we have added all values of this meta elem
302 }
303 // otherwise, we will keep going through the list and add them all.
304 }
305 }
306 */
307
308 // specific metadata formats might need to do some custom metadata that is not
309 //just a standard mapping.
310 /*
311 protected void addCustomMetadata(Element meta_list_elem, String prefix, DBInfo info) {
312
313
314 }
315 */
316
317 /** create the actual metadata element for the list */
318
319 protected void addMetadataElement(Element meta_list_elem, String name, String value) {
320
321 Element meta = GSXML.createTextElement(meta_list_elem.getOwnerDocument(), name, value);
322 meta_list_elem.appendChild(meta);
323 }
324
325
326 /** create a header element used when processing requests like GetRecord
327 */
328 protected Element createHeaderElement(Document doc, String oid) {
329
330 Element header = doc.createElement(IIIFXML.HEADER);
331
332 Element identifier = doc.createElement(IIIFXML.IDENTIFIER);
333 GSXML.setNodeText(identifier, coll_name + ":" + oid);
334 header.appendChild(identifier);
335
336 return header;
337 }
338
339}
340
341
Note: See TracBrowser for help on using the repository browser.