# HG changeset patch
# User robcast
# Date 1374050741 -7200
# Node ID 2c448b6b21da142a393e2c7ab92f028883ca6682
# Parent 2cba651b91ce2a892279f3721131648e8d4b30fb
starting IIIF image api parser.
diff -r 2cba651b91ce -r 2c448b6b21da common/src/main/java/digilib/conf/DigilibRequest.java
--- a/common/src/main/java/digilib/conf/DigilibRequest.java Tue Jul 16 13:39:22 2013 +0200
+++ b/common/src/main/java/digilib/conf/DigilibRequest.java Wed Jul 17 10:45:41 2013 +0200
@@ -33,6 +33,8 @@
import java.net.URLDecoder;
import java.util.StringTokenizer;
+import org.apache.log4j.Logger;
+
import digilib.image.ImageJobDescription;
import digilib.io.FileOps;
import digilib.util.OptionsSet;
@@ -42,7 +44,7 @@
/**
* Class holding the parameters of a digilib user request. The parameters are
* mostly named like the servlet parameters:
- * request_path: url of the page/document.
+ * request.path: url of the page/document.
* fn: url of the page/document.
* pn: page number.
* dw: width of result window in pixels.
@@ -52,10 +54,7 @@
* ww: width of image area(float from 0 to 1).
* wh: height of image area(float from 0 to 1).
* ws: scale factor.
- * mo: special options like 'fit' for gifs.
- * mk: list of marks.
- * pt: total number of pages (generated by sevlet).
- * baseURL: base URL (from http:// to below /servlet).
+ * mo: special options like 'fit'.
* ...et alii
*
* @author casties
@@ -63,19 +62,24 @@
*/
public class DigilibRequest extends ParameterMap {
- /** ImageJobDescription for this request */
- protected ImageJobDescription ticket;
-
- /** DigilibConfiguration for this request */
- protected DigilibConfiguration config;
+ private static Logger logger = Logger.getLogger("digilib.request");
+
+ // TODO: make prefix configurable
+ public static final String iiifPrefix = "iiif";
+
+ /** ImageJobDescription for this request */
+ protected ImageJobDescription ticket;
- public DigilibRequest() {
- super(30);
- }
+ /** DigilibConfiguration for this request */
+ protected DigilibConfiguration config;
- /**
- * Create DigilibRequest with DigilibConfiguration.
- *
+ public DigilibRequest() {
+ super(30);
+ }
+
+ /**
+ * Create DigilibRequest with DigilibConfiguration.
+ *
* @param config
*/
public DigilibRequest(DigilibConfiguration config) {
@@ -83,90 +87,85 @@
this.config = config;
}
- /** set up parameters.
- *
- */
- protected void initParams() {
- /*
- * Definition of parameters and default values. Parameter of type 's'
- * are for the servlet.
- */
+ /**
+ * set up parameters.
+ *
+ */
+ protected void initParams() {
+ /*
+ * Definition of parameters and default values. Parameter of type 's'
+ * are for the servlet.
+ */
- // url of the page/document (second part)
- newParameter("fn", "", null, 's');
- // page number
- newParameter("pn", new Integer(1), null, 's');
- // width of client in pixels
- newParameter("dw", new Integer(0), null, 's');
- // height of client in pixels
- newParameter("dh", new Integer(0), null, 's');
- // left edge of image (float from 0 to 1)
- newParameter("wx", new Float(0), null, 's');
- // top edge in image (float from 0 to 1)
- newParameter("wy", new Float(0), null, 's');
- // width of image (float from 0 to 1)
- newParameter("ww", new Float(1), null, 's');
- // height of image (float from 0 to 1)
- newParameter("wh", new Float(1), null, 's');
- // scale factor
- newParameter("ws", new Float(1), null, 's');
- // special options like 'fit' for gifs
- newParameter("mo", this.options, null, 's');
- // rotation angle (degree)
- newParameter("rot", new Float(0), null, 's');
- // contrast enhancement factor
- newParameter("cont", new Float(0), null, 's');
- // brightness enhancement factor
- newParameter("brgt", new Float(0), null, 's');
- // color multiplicative factors
- newParameter("rgbm", "0/0/0", null, 's');
- // color additive factors
- newParameter("rgba", "0/0/0", null, 's');
- // display dpi resolution (total)
- newParameter("ddpi", new Float(0), null, 's');
- // display dpi X resolution
- newParameter("ddpix", new Float(0), null, 's');
- // display dpi Y resolution
- newParameter("ddpiy", new Float(0), null, 's');
- // scale factor for mo=ascale
- newParameter("scale", new Float(1), null, 's');
- // color conversion operation
- newParameter("colop", "", null, 's');
+ // url of the page/document (second part)
+ newParameter("fn", "", null, 's');
+ // page number
+ newParameter("pn", new Integer(1), null, 's');
+ // width of client in pixels
+ newParameter("dw", new Integer(0), null, 's');
+ // height of client in pixels
+ newParameter("dh", new Integer(0), null, 's');
+ // left edge of image (float from 0 to 1)
+ newParameter("wx", new Float(0), null, 's');
+ // top edge in image (float from 0 to 1)
+ newParameter("wy", new Float(0), null, 's');
+ // width of image (float from 0 to 1)
+ newParameter("ww", new Float(1), null, 's');
+ // height of image (float from 0 to 1)
+ newParameter("wh", new Float(1), null, 's');
+ // scale factor
+ newParameter("ws", new Float(1), null, 's');
+ // special options like 'fit' for gifs
+ newParameter("mo", this.options, null, 's');
+ // rotation angle (degree)
+ newParameter("rot", new Float(0), null, 's');
+ // contrast enhancement factor
+ newParameter("cont", new Float(0), null, 's');
+ // brightness enhancement factor
+ newParameter("brgt", new Float(0), null, 's');
+ // color multiplicative factors
+ newParameter("rgbm", "0/0/0", null, 's');
+ // color additive factors
+ newParameter("rgba", "0/0/0", null, 's');
+ // display dpi resolution (total)
+ newParameter("ddpi", new Float(0), null, 's');
+ // display dpi X resolution
+ newParameter("ddpix", new Float(0), null, 's');
+ // display dpi Y resolution
+ newParameter("ddpiy", new Float(0), null, 's');
+ // scale factor for mo=ascale
+ newParameter("scale", new Float(1), null, 's');
+ // color conversion operation
+ newParameter("colop", "", null, 's');
- /*
- * Parameters of type 'i' are not exchanged between client and server,
- * but are for the servlets or JSPs internal use.
- */
+ /*
+ * Parameters of type 'i' are not exchanged between client and server,
+ * but are for the servlets or JSPs internal use.
+ */
- // url of the page/document (first part, may be empty)
- newParameter("request.path", "", null, 'i');
- // base URL (from http:// to below /servlet)
- newParameter("base.url", null, null, 'i');
- /*
- * Parameters of type 'c' are for the clients use
- */
+ // url of the page/document (first part, may be empty)
+ newParameter("request.path", "", null, 'i');
+ // base URL (from http:// to below /servlet)
+ newParameter("base.url", null, null, 'i');
+ /*
+ * Parameters of type 'c' are for the clients use
+ */
- // "real" filename
- newParameter("img.fn", "", null, 'c');
- // image dpi x
- newParameter("img.dpix", new Integer(0), null, 'c');
- // image dpi y
- newParameter("img.dpiy", new Integer(0), null, 'c');
- // hires image size x
- newParameter("img.pix_x", new Integer(0), null, 'c');
- // hires image size y
- newParameter("img.pix_y", new Integer(0), null, 'c');
- // total number of pages
- newParameter("pt", new Integer(0), null, 'c');
- // display level of digilib (0 = just image, 1 = one HTML page
- // 2 = in frameset, 3 = XUL-'frameset'
- // 4 = XUL-Sidebar )
- newParameter("lv", new Integer(2), null, 'c');
- // marks
- newParameter("mk", "", null, 'c');
- }
+ // "real" filename
+ newParameter("img.fn", "", null, 'c');
+ // image dpi x
+ newParameter("img.dpix", new Integer(0), null, 'c');
+ // image dpi y
+ newParameter("img.dpiy", new Integer(0), null, 'c');
+ // hires image size x
+ newParameter("img.pix_x", new Integer(0), null, 'c');
+ // hires image size y
+ newParameter("img.pix_y", new Integer(0), null, 'c');
+ }
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see digilib.servlet.ParameterMap#initOptions()
*/
@Override
@@ -174,127 +173,238 @@
options = (OptionsSet) getValue("mo");
}
- /**
- * Return the request parameters as a String in the parameter form
- * 'fn=/icons&pn=1'. Empty (undefined) fields are not included.
- *
- * @return String of request parameters in parameter form.
- */
- public String getAsString() {
- return getAsString(0);
- }
+ /**
+ * Return the request parameters as a String in the parameter form
+ * 'fn=/icons&pn=1'. Empty (undefined) fields are not included.
+ *
+ * @return String of request parameters in parameter form.
+ */
+ public String getAsString() {
+ return getAsString(0);
+ }
- /**
- * Return the request parameters of a given type type as a String in the
- * parameter form 'fn=/icons&pn=1'. Empty (undefined) fields are not
- * included.
- *
- * @return String of request parameters in parameter form.
- */
- public String getAsString(int type) {
- StringBuffer s = new StringBuffer(50);
- // go through all values
- for (Parameter p: params.values()) {
- if ((type > 0) && (p.getType() != type)) {
- // skip the wrong types
- continue;
- }
- String name = p.getName();
- /*
- * handling special cases
- */
- // request_path adds to fn
- if (name.equals("fn")) {
- s.append("&fn=" + getAsString("request.path")
- + getAsString("fn"));
- continue;
- }
- /*
- * the rest is sent with its name
- */
- // parameters that are not set or internal are not sent
- if ((!p.hasValue()) || (p.getType() == 'i')) {
- continue;
- }
- s.append("&" + name + "=" + p.getAsString());
- }
- // kill first "&"
- s.deleteCharAt(0);
- return s.toString();
- }
+ /**
+ * Return the request parameters of a given type type as a String in the
+ * parameter form 'fn=/icons&pn=1'. Empty (undefined) fields are not
+ * included.
+ *
+ * @return String of request parameters in parameter form.
+ */
+ public String getAsString(int type) {
+ StringBuffer s = new StringBuffer(50);
+ // go through all values
+ for (Parameter p : params.values()) {
+ if ((type > 0) && (p.getType() != type)) {
+ // skip the wrong types
+ continue;
+ }
+ String name = p.getName();
+ /*
+ * handling special cases
+ */
+ // request_path adds to fn
+ if (name.equals("fn")) {
+ s.append("&fn=" + getAsString("request.path") + getAsString("fn"));
+ continue;
+ }
+ /*
+ * the rest is sent with its name
+ */
+ // parameters that are not set or internal are not sent
+ if ((!p.hasValue()) || (p.getType() == 'i')) {
+ continue;
+ }
+ s.append("&" + name + "=" + p.getAsString());
+ }
+ // kill first "&"
+ s.deleteCharAt(0);
+ return s.toString();
+ }
+
+ /**
+ * Set request parameters from query string. Uses the separator string qs to
+ * get 'fn=foo' style parameters.
+ *
+ * @param qs
+ * query string
+ * @param sep
+ * parameter-separator string
+ */
+ public void setWithParamString(String qs, String sep) {
+ // go through all request parameters
+ String[] qa = qs.split(sep);
+ for (int i = 0; i < qa.length; i++) {
+ // split names and values on "="
+ String[] nv = qa[i].split("=");
+ try {
+ String name = URLDecoder.decode(nv[0], "UTF-8");
+ String val = URLDecoder.decode(nv[1], "UTF-8");
+ // is this a known parameter?
+ if (params.containsKey(name)) {
+ Parameter p = (Parameter) this.get(name);
+ // internal parameters are not set
+ if (p.getType() == 'i') {
+ continue;
+ }
+ p.setValueFromString(val);
+ continue;
+ }
+ // unknown parameters are just added with type 'r'
+ newParameter(name, null, val, 'r');
+ } catch (UnsupportedEncodingException e) {
+ // this shouldn't happen anyway
+ e.printStackTrace();
+ }
+ }
+ }
- /**
- * Set request parameters from query string. Uses the separator string qs to
- * get 'fn=foo' style parameters.
- *
- * @param qs
- * query string
- * @param sep
- * parameter-separator string
- */
- public void setWithParamString(String qs, String sep) {
- // go through all request parameters
- String[] qa = qs.split(sep);
- for (int i = 0; i < qa.length; i++) {
- // split names and values on "="
- String[] nv = qa[i].split("=");
- try {
- String name = URLDecoder.decode(nv[0], "UTF-8");
- String val = URLDecoder.decode(nv[1], "UTF-8");
- // is this a known parameter?
- if (params.containsKey(name)) {
- Parameter p = (Parameter) this.get(name);
- // internal parameters are not set
- if (p.getType() == 'i') {
- continue;
- }
- p.setValueFromString(val);
- continue;
- }
- // unknown parameters are just added with type 'r'
- newParameter(name, null, val, 'r');
- } catch (UnsupportedEncodingException e) {
- // this shouldn't happen anyway
- e.printStackTrace();
- }
- }
- }
+ /**
+ * Populate a request from a string with an IIIF Image API path.
+ *
+ * @param path
+ * String with IIIF Image API path.
+ *
+ * @see IIIF Image
+ * API
+ */
+ public void setWithIiifPath(String path) {
+ if (path == null) {
+ return;
+ }
+ // enable the passing of delimiter to get empty parameters
+ StringTokenizer query = new StringTokenizer(path, "/", true);
+ String token;
+ // first parameter prefix
+ if (query.hasMoreTokens()) {
+ token = query.nextToken();
+ if (!token.equals(iiifPrefix)) {
+ logger.error("IIIF path doesn't start with prefix!");
+ // what now?
+ }
+ // skip /
+ if (query.hasMoreTokens()) {
+ query.nextToken();
+ }
+ }
+ // second parameter FN (encoded)
+ if (query.hasMoreTokens()) {
+ token = query.nextToken();
+ if (!token.equals("/")) {
+ try {
+ setValueFromString("fn", URLDecoder.decode(token, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ logger.error("Error decoding identifier in IIIF path!");
+ }
+ // skip /
+ if (query.hasMoreTokens()) {
+ query.nextToken();
+ }
+ }
+ }
+ // third parameter region
+ if (query.hasMoreTokens()) {
+ token = query.nextToken();
+ if (!token.equals("/")) {
+ if (token.equals("full")) {
+ // full region -- default
+ } else if (token.startsWith("pct:")){
+ // region in % of original image
+ String[] params = token.substring(4).split(",");
+ try {
+ float x = Float.parseFloat(params[0]);
+ setValue("wx", x / 100f);
+ float y = Float.parseFloat(params[1]);
+ setValue("wy", y / 100f);
+ float w = Float.parseFloat(params[2]);
+ setValue("ww", w / 100f);
+ float h = Float.parseFloat(params[3]);
+ setValue("wh", h / 100f);
+ } catch (Exception e) {
+ logger.error("Error parsing range parameter in IIIF path!");
+ }
+ } else {
+ // region in pixel of original image :-(
+ logger.error("pixel region not yet implemented");
+ }
+ // skip /
+ if (query.hasMoreTokens()) {
+ query.nextToken();
+ }
+ }
+ }
+ // fourth parameter size
+ if (query.hasMoreTokens()) {
+ token = query.nextToken();
+ if (!token.equals("/")) {
+ // TODO
+ setValueFromString("mo", token);
+ // skip /
+ if (query.hasMoreTokens()) {
+ query.nextToken();
+ }
+ }
+ }
+ // fifth parameter rotation
+ if (query.hasMoreTokens()) {
+ token = query.nextToken();
+ if (!token.equals("/")) {
+ setValueFromString("rot", token);
+ // skip /
+ if (query.hasMoreTokens()) {
+ query.nextToken();
+ }
+ }
+ }
+ // sixth parameter quality.format
+ if (query.hasMoreTokens()) {
+ token = query.nextToken();
+ if (!token.equals("/")) {
+ // TODO
+ setValueFromString("wx", token);
+ // skip /
+ if (query.hasMoreTokens()) {
+ query.nextToken();
+ }
+ }
+ }
+ }
- /**
- * Test if option string opt
is set. Checks if the substring
- * opt
is contained in the options string param
.
- * Deprecated! use hasOption(String opt) for "mo"-options.
- *
- * @param opt
- * Option string to be tested.
- * @return boolean
- */
- public boolean hasOption(String param, String opt) {
- String s = getAsString(param);
- if (s != null) {
- StringTokenizer i = new StringTokenizer(s, ",");
- while (i.hasMoreTokens()) {
- if (i.nextToken().equals(opt)) {
- return true;
- }
- }
- }
- return false;
- }
+ /**
+ * Test if option string opt
is set. Checks if the substring
+ * opt
is contained in the options string param
.
+ *
+ * @param opt
+ * Option string to be tested.
+ * @return boolean
+ *
+ * @deprecated use hasOption(String opt) for "mo"-options.
+ */
+ public boolean hasOption(String param, String opt) {
+ String s = getAsString(param);
+ if (s != null) {
+ StringTokenizer i = new StringTokenizer(s, ",");
+ while (i.hasMoreTokens()) {
+ if (i.nextToken().equals(opt)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
- /**
- * The image file path to be accessed.
- *
- * The mage file path is assembled from the servlets RequestPath and
- * Parameter fn and normalized.
- *
- * @return String the effective filepath.
- */
- public String getFilePath() {
- String s = getAsString("request.path");
- s += getAsString("fn");
- return FileOps.normalName(s);
- }
+ /**
+ * The image file path to be accessed.
+ *
+ * The image file path is assembled from the servlets RequestPath and
+ * Parameter fn and normalized.
+ *
+ * @return String the effective filepath.
+ */
+ public String getFilePath() {
+ String s = getAsString("request.path");
+ s += getAsString("fn");
+ return FileOps.normalName(s);
+ }
/**
* @return the ticket
@@ -304,7 +414,8 @@
}
/**
- * @param ticket the ticket to set
+ * @param ticket
+ * the ticket to set
*/
public void setJobDescription(ImageJobDescription ticket) {
this.ticket = ticket;
@@ -318,7 +429,8 @@
}
/**
- * @param config the config to set
+ * @param config
+ * the config to set
*/
public void setDigilibConfig(DigilibConfiguration config) {
this.config = config;
diff -r 2cba651b91ce -r 2c448b6b21da servlet/src/main/java/digilib/conf/DigilibServletRequest.java
--- a/servlet/src/main/java/digilib/conf/DigilibServletRequest.java Tue Jul 16 13:39:22 2013 +0200
+++ b/servlet/src/main/java/digilib/conf/DigilibServletRequest.java Wed Jul 17 10:45:41 2013 +0200
@@ -27,8 +27,6 @@
* Christian Luginbuehl
*/
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.StringTokenizer;
@@ -171,10 +169,13 @@
newParameter("img.pix_x", new Integer(0), null, 'c');
// hires image size y
newParameter("img.pix_y", new Integer(0), null, 'c');
- // total number of pages
- newParameter("pt", new Integer(0), null, 'c');
- // marks
- newParameter("mk", "", null, 'c');
+ /*
+ * TODO: check if we can remove these
+ * // total number of pages
+ * newParameter("pt", new Integer(0), null, 'c');
+ * // marks
+ * newParameter("mk", "", null, 'c');
+ */
}
/*
@@ -195,25 +196,32 @@
*/
public void setWithRequest(HttpServletRequest request) {
servletRequest = request;
- // decide if it's old-style or new-style
- String qs = ((HttpServletRequest) request).getQueryString();
- if (qs != null) {
- if (qs.indexOf("&") > -1) {
- // & separator
- setWithParamString(qs, "&");
- } else if (qs.indexOf(";") > -1) {
- // ; separator
- setWithParamString(qs, ";");
- } else if (qs.indexOf('=') > -1) {
- // standard '&' parameters
- setWithParamRequest(request);
- } else {
- setWithOldString(qs);
+ setValue("servlet.request", request);
+ // request path (after servlet, before "?")
+ String path = ((HttpServletRequest) request).getPathInfo();
+ // decide if its IIIF API
+ if (path != null && path.startsWith(iiifPrefix, 1)) {
+ setWithIiifPath(path.substring(1));
+ } else {
+ // decide if it's old-style or new-style digilib
+ String qs = ((HttpServletRequest) request).getQueryString();
+ if (qs != null) {
+ if (qs.indexOf("&") > -1) {
+ // & separator
+ setWithParamString(qs, "&");
+ } else if (qs.indexOf(";") > -1) {
+ // ; separator
+ setWithParamString(qs, ";");
+ } else if (qs.indexOf('=') > -1) {
+ // standard '&' parameters
+ setWithParamRequest(request);
+ } else {
+ setWithOldString(qs);
+ }
}
+ // add path from request
+ setValue("request.path", path);
}
- setValue("servlet.request", request);
- // add path from request
- setValue("request.path", ((HttpServletRequest) request).getPathInfo());
// set the baseURL
setBaseURL((HttpServletRequest) request);
}
@@ -423,65 +431,6 @@
setValue("request.path", ((HttpServletRequest) request).getPathInfo());
}
- /**
- * Set request parameters from query string. Uses the separator string qs to
- * get 'fn=foo' style parameters.
- *
- * @param qs
- * query string
- * @param sep
- * parameter-separator string
- */
- public void setWithParamString(String qs, String sep) {
- // go through all request parameters
- String[] qa = qs.split(sep);
- for (int i = 0; i < qa.length; i++) {
- // split names and values on "="
- String[] nv = qa[i].split("=");
- try {
- String name = URLDecoder.decode(nv[0], "UTF-8");
- String val = URLDecoder.decode(nv[1], "UTF-8");
- // is this a known parameter?
- if (params.containsKey(name)) {
- Parameter p = (Parameter) this.get(name);
- // internal parameters are not set
- if (p.getType() == 'i') {
- continue;
- }
- p.setValueFromString(val);
- continue;
- }
- // unknown parameters are just added with type 'r'
- newParameter(name, null, val, 'r');
- } catch (UnsupportedEncodingException e) {
- // this shouldn't happen anyway
- e.printStackTrace();
- }
- }
- }
-
- /**
- * Test if option string opt
is set. Checks if the substring
- * opt
is contained in the options string param
.
- * Deprecated! use hasOption(String opt) for "mo"-options.
- *
- * @param opt
- * Option string to be tested.
- * @return boolean
- */
- public boolean hasOption(String param, String opt) {
- String s = getAsString(param);
- if (s != null) {
- StringTokenizer i = new StringTokenizer(s, ",");
- while (i.hasMoreTokens()) {
- if (i.nextToken().equals(opt)) {
- return true;
- }
- }
- }
- return false;
- }
-
/* Property getter and setter */
/**
@@ -495,7 +444,7 @@
String baseURL = null;
// calculate base URL string from request until webapp
String s = request.getRequestURL().toString();
- // get name of webapp
+ // get name of webapp
String wn = request.getContextPath();
int eop = s.lastIndexOf(wn);
if (eop > 0) {