source: gs3-extensions/iiif-servlet/trunk/src/gsdl-src/java/org/greenstone/gsdl3/util/IIIFXML.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: 12.4 KB
Line 
1/*
2 * IIIFXML.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.util;
20
21import org.greenstone.util.GlobalProperties;
22
23import org.w3c.dom.*;
24
25import java.io.*;
26import java.net.*;
27import java.util.*;
28import java.text.DateFormat;
29import java.text.SimpleDateFormat;
30
31// import file Logger.java
32import org.apache.log4j.*;
33
34/** these constants are used for the IIIF service */
35public class IIIFXML {
36
37 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.IIIFXML.class.getName());
38
39 // the leading keyword of IIIF protocol // ****
40 public static final String VERB = "verb";
41
42 // Possible states for non-IIIF/non-verb activate/deactivate requests
43 public static final int DEACTIVATION = 0;
44 public static final int ACTIVATION = 1;
45
46 // one valid iiif verb // ****
47 public static final String GET_RECORD = "GetRecord";
48
49 // iiif request parameters
50 public static final String IDENTIFIER = "identifier";
51
52 // Error element and code att
53 public static final String ERROR = "error";
54 public static final String CODE = "code";
55
56 // IIIF error codes
57 public static final String ID_DOES_NOT_EXIST = "idDoesNotExist";
58
59 // General
60 public static final String IIIF_PMH = "IIIF-PMH"; // ****
61 public static final String RESPONSE_DATE = "responseDate"; // ****
62 public static final String REQUEST = "request";
63
64 // Identify data
65 // OAI replacing => IIIF, maybe want baseURL and oai-identifier
66 public static final String BASE_URL = "baseURL";
67
68 // record response data
69 public static final String RECORD = "record";
70 public static final String HEADER = "header";
71 public static final String METADATA = "metadata";
72
73 //public static final String OAIPMH = "OAIPMH"; // ****
74
75 //public static final String OAI_SET_LIST = "oaiSetList"; // ****
76 //public static final String OAI_SERVICE_UNAVAILABLE = "OAI service unavailable";
77 public static final String OID = "OID"; // ****
78
79 public static final String IIIF_SERVICE_RACK = "IIIFPMH";
80 //system-dependent file separator, maybe '/' or '\'
81 //public static final String FILE_SEPARATOR = File.separator;
82 //public static final String OAI_VERSION1 = "1.0";
83 //public static final String IIIF_VERSION2 = "2.1"; // ****
84 /*************************above are final values****************************/
85
86
87 //initialized in getIIIFConfigXML()
88 public static Element iiif_config_elem = null;
89
90 public static final String iiif_version = "2.1"; // ****
91 public static String baseURL = "";
92
93 /** Converter for parsing files and creating Elements */
94 public static XMLConverter converter = new XMLConverter();
95
96 public static String[] special_char = {"/", "?", "#", "=", "&", ":", ";", " ", "%", "+"};
97 public static String[] escape_sequence = {"%2F", "%3F", "%23", "%3D", "%26", "%3A", "%3B", "%20", "%25", "%2B"};
98
99 public static String getIIIFVersion() {
100 return iiif_version;
101 }
102
103 public static String getBaseURL() {
104 return baseURL;
105 }
106
107 /** Read in IIIFConfig.xml (residing web/WEB-INF/classes/) and use it to configure the receptionist etc.
108 * the baseURL variables are also set in here.
109 * The init() method is also called in here. */
110 public static Element getIIIFConfigXML() {
111
112 File iiif_config_file = null;
113
114 try {
115 URL iiif_config_url = Class.forName("org.greenstone.gsdl3.IIIFServerBridge").getClassLoader().getResource("IIIFConfig.xml");
116 if (iiif_config_url == null) {
117 logger.error("couldn't find IIIFConfig.xml via class loader");
118 return null;
119 }
120 iiif_config_file = new File(iiif_config_url.toURI());
121 if (!iiif_config_file.exists()) {
122 logger.error(" IIIF config file: "+iiif_config_file.getPath()+" not found!");
123 return null;
124 }
125 } catch(Exception e) {
126 logger.error("couldn't find IIIFConfig.xml "+e.getMessage());
127 return null;
128 }
129
130 Document iiif_config_doc = converter.getDOM(iiif_config_file, "utf-8");
131 if (iiif_config_doc != null) {
132 iiif_config_elem = iiif_config_doc.getDocumentElement();
133 } else {
134 logger.error("Failed to parse IIIF config file IIIFConfig.xml.");
135 return null;
136 }
137
138 // initialize baseURL
139 Element base_url_elem = (Element)GSXML.getChildByTagName(iiif_config_elem, BASE_URL);
140 baseURL = GSXML.getNodeText(base_url_elem);
141
142 return iiif_config_elem;
143 }
144
145
146 /** TODO: returns a basic response (loosely based on OAI XML message)
147 *
148 */
149 public static Element createBasicResponse(Document doc, String verb, String[] pairs) { // ****
150
151 Element response = createResponseHeader(doc, verb);
152
153 //set the responseDate and request elements accordingly
154 Element request_elem = (Element)GSXML.getChildByTagName(response, REQUEST);
155 if (verb.equals("")) {
156 request_elem.setAttribute(VERB, verb);
157 }
158 int num_pairs = (pairs==null)? 0 : pairs.length;
159 for (int i=num_pairs - 1; i>=0; i--) {
160 int index = pairs[i].indexOf("=");
161 if (index != -1) {
162 String[] strs = pairs[i].split("=");
163 if(strs != null && strs.length == 2) {
164 request_elem.setAttribute(strs[0], iiifDecode(strs[1]));
165 }
166 }
167 }//end of for()
168
169 GSXML.setNodeText(request_elem, baseURL);
170
171 //Node resp_date = GSXML.getChildByTagName(response, RESPONSE_DATE); // ****
172
173 return response;
174 }
175
176 /** @param error_code the value of the code attribute
177 * @param error_text the node text of the error element
178 * @return an iiif error <message><response><error>
179 */
180 public static Element createErrorMessage(String error_code, String error_text) {
181 Document doc = converter.newDOM();
182 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
183 Element resp = doc.createElement(GSXML.RESPONSE_ELEM);
184 message.appendChild(resp);
185 Element error = createErrorElement(doc, error_code, error_text);
186 resp.appendChild(error);
187 return message;
188 }
189
190 /** @param error_code the value of the code attribute
191 * @param error_text the node text of the error element
192 * @return an iiif error <response><error>
193 */
194 public static Element createErrorResponse(String error_code, String error_text) {
195 Document doc = converter.newDOM();
196 Element resp = doc.createElement(GSXML.RESPONSE_ELEM);
197 Element error = createErrorElement(doc, error_code, error_text);
198 resp.appendChild(error);
199 return resp;
200 }
201
202 /** @param error_code the value of the code attribute
203 * @param error_text the node text of the error element
204 * @return an iiif error <error>
205 */
206 public static Element createErrorElement(Document doc, String error_code, String error_text) {
207 Element error = doc.createElement(ERROR);
208 error.setAttribute(CODE, error_code);
209 GSXML.setNodeText(error, error_text);
210 return error;
211 }
212
213 // This is the response message sent when there's a request to activate/deactivate a non-OAI collection
214 // A request to activate a non-existent/non-OAI collection is not invalid, it's just that we won't process it.
215 // So we still return status code OK (OK status code is needed for servercontrol.pm of activate.pl to recognise
216 // that the command had been "successful" when it runs de/activate).
217 public static Element createDeActivationOfNonIIIFCollResponse(int activationState, String collname) {
218 Document doc = converter.newDOM();
219 Element response = doc.createElement(GSXML.RESPONSE_ELEM);
220 response.setAttribute("status", "OK");
221 String message = "collection: " + collname + " is not enabled for IIIF.";
222 if(activationState == ACTIVATION) {
223 message += " Not attempting to activate it.";
224 } else {
225 message += " Not attempting to deactivate it.";
226 }
227 GSXML.setNodeText(response, message);
228 return response;
229 }
230
231 // The response message sent when a request comes in to activate/deactivate a proper IIIF collection.
232 public static Element createActivationStateResponse(boolean success, int activationState, String collname) {
233 Document doc = converter.newDOM();
234 Element response = doc.createElement(GSXML.RESPONSE_ELEM);
235 if (success) {
236 response.setAttribute("status", "OK");
237 if(activationState == ACTIVATION) {
238 GSXML.setNodeText(response, "collection: " + collname + " activated");
239 } else {
240 GSXML.setNodeText(response, "collection: " + collname + " deactivated");
241 }
242 } else {
243 response.setAttribute("status", "FAIL");
244 if(activationState == ACTIVATION) {
245 GSXML.setNodeText(response, "Failed to activate collection " + collname);
246 } else {
247 GSXML.setNodeText(response, "Failed to deactivate collection " + collname);
248 }
249 }
250 return response;
251 }
252
253 public static Element createResetResponse(boolean success) {
254 Document doc = converter.newDOM();
255 Element response = doc.createElement(GSXML.RESPONSE_ELEM);
256 if (success) {
257 response.setAttribute("status", "OK");
258 GSXML.setNodeText(response, "Reset IIIFServerBridge successfully");
259 } else {
260 response.setAttribute("status", "FAIL");
261 GSXML.setNodeText(response, "Failed to reset IIIFServerBridge");
262 }
263 return response;
264 }
265 /** convert the escaped sequences (eg, '%3A') of those special characters back to their
266 * original form (eg, ':').
267 */
268 public static String iiifDecode(String escaped_str) {
269 logger.info("iiifDecode() " +escaped_str);
270 for (int i=0; i<special_char.length; i++) {
271 if (escaped_str.indexOf(escape_sequence[i]) != -1) {
272 escaped_str = escaped_str.replaceAll(escape_sequence[i], special_char[i]);
273 }
274 }
275 return escaped_str;
276 }
277 /** convert those special characters (eg, ':') to their
278 * escaped sequences (eg, '%3A').
279 */
280 public static String iiifEncode(String original_str) { // ****
281 logger.info("iiifEncode() " + original_str);
282 for (int i=0; i<special_char.length; i++) {
283 if (original_str.indexOf(special_char[i]) != -1) {
284 original_str = original_str.replaceAll(special_char[i], escape_sequence[i]);
285 }
286 }
287 return original_str;
288 }
289
290 public static Element createResponseHeader(Document response_doc, String verb) {
291 //String tag_name = (iiif_version.equals(IIIF_VERSION2))? IIIF_PMH : verb; // ****
292 String tag_name = IIIF_PMH;
293 Element iiif = response_doc.createElement(tag_name);
294 //Element resp_date = response_doc.createElement(RESPONSE_DATE); // ****
295 Element req = response_doc.createElement(REQUEST);
296 //oai.appendChild(resp_date);
297 iiif.appendChild(req);
298
299 return iiif;
300 }
301
302 /*
303 public static Element createOAIIdentifierXML(Document doc, String repository_id, String sample_collection, String sample_doc_id) {
304 String xml = "<oai-identifier xmlns=\"http://www.openarchives.org/OAI/2.0/oai-identifier\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xsi:schemaLocation=\"http://www.openarchives.org/OAI/2.0/oai-identifier\n http://www.openarchives.org/OAI/2.0/oai-identifier.xsd\">\n <scheme>oai</scheme>\n<repositoryIdentifier>" + repository_id + "</repositoryIdentifier>\n<delimiter>:</delimiter>\n<sampleIdentifier>oai:"+repository_id+":"+sample_collection+":"+sample_doc_id+"</sampleIdentifier>\n</oai-identifier>";
305
306 Document xml_doc = converter.getDOM(xml);
307 return (Element)doc.importNode(xml_doc.getDocumentElement(), true);
308
309
310 }
311 */
312
313 /*
314 public static Element createGSDLElement(Document doc) {
315 String xml = "<gsdl xmlns=\"http://www.greenstone.org/namespace/gsdl_oaiinfo/1.0/gsdl_oaiinfo\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xsi:schemaLocation=\"http://www.greenstone.org/namespace/gsdl_oaiinfo/1.0/gsdl_oaiinfo\n http://www.greenstone.org/namespace/gsdl_oaiinfo/1.0/gsdl_oaiinfo.xsd\"></gsdl>";
316 Document xml_doc = converter.getDOM(xml);
317 return (Element)doc.importNode(xml_doc.getDocumentElement(), true);
318 }
319 */
320
321}
322
323
324
325
326
327
Note: See TracBrowser for help on using the repository browser.