From 5b978e6919af8e8548337cd1ab1ce1df625f74f1 Mon Sep 17 00:00:00 2001 From: "Niels Erik G. Nielsen" Date: Wed, 15 May 2013 12:45:14 -0400 Subject: [PATCH] Bugfixes for browser history management. Documentation. --- src/META-INF/resources/pz2utils/listeners.js | 52 +++++++++++--------- src/META-INF/resources/pz2utils/pz2watch.xhtml | 2 +- .../java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java | 26 ++++++++-- .../mkjsf/pazpar2/data/RecordResponse.java | 5 +- .../mkjsf/pazpar2/state/StateManager.java | 29 +++++++---- 5 files changed, 76 insertions(+), 38 deletions(-) diff --git a/src/META-INF/resources/pz2utils/listeners.js b/src/META-INF/resources/pz2utils/listeners.js index 056723e..3bbfa2b 100644 --- a/src/META-INF/resources/pz2utils/listeners.js +++ b/src/META-INF/resources/pz2utils/listeners.js @@ -46,24 +46,35 @@ function renderOnRecordTargets(doRefresh) { } } -// Listens for browser initiated changes to 'window.location.hash' and sends the -// hash -// changes to the back-end (to have the back-end pull up a previous Pazpar2 -// state) +// Listens for browser initiated changes to 'window.location.hash' and sends +// the hash key changes to the back-end, to have the back-end pull up a previous +// Pazpar2 state. +// +// See also: The field in pz2watch.xhtml, the StateListener function below, +// the method Pz2Bean.handleQueryStateChanges(), and the classes +// Pazpar2State and StateManager for a complete picture of browser history +// handling. function windowlocationhashListener() { if (trackHistory) { - // console.log("browser hash update detected"); + var stateKey = document.getElementById("pz2watch:windowlocationhash"); - if (window.location.hash != stateKey.value) { - // console.log("updating stateKey with new browser hash: " + - // window.location.hash); - stateKey.value = window.location.hash; - if (!stateKey.value) - window.location.hash = '#1'; - stateKey.onchange(); + // console.log("browser hash update response detected."); + // console.log("pz2watch:windowlocationhash: [" + stateKey.value + "]"); + // console.log("window.location.hash: [" + window.location.hash + "]"); + if (window.location.hash != stateKey.value) { + if (window.location.hash) { + //console.log("updating pz2watch:windowlocationhash with new window.location.hash [" + window.location.hash + "]"); + stateKey.value = window.location.hash; + //console.log("firing pz2watch:windowlocationhash onChange"); + stateKey.onchange(); + } else if (stateKey.value) { + //console.log("updating window.location.hash with pz2watch:windowlocationhash [" + stateKey.value + "]"); + window.location.hash = stateKey.value; + //console.log("firing pz2watch:windowlocationhash onChange"); + stateKey.onchange(); + } } else { - // console.log("State hash already has the value of the new browser hash - - // not updating state hash"); + //console.log("State hash already has the value of the new browser hash - not updating state hash"); } } } @@ -139,14 +150,12 @@ var StateListener = function() { this.invoke = function(field) { var stateKeyDoc = StringtoXML(field.textContent || field.text); var stateKeyValue = stateKeyDoc.childNodes[0].getAttribute("value"); - // console.log('Application hash update detected. New value: ' + - // stateKeyValue); + // console.log('Received state key update from the back-end: ' + stateKeyValue); if (stateKeyValue !== window.location.hash) { window.location.hash = stateKeyValue; - // console.log("Browsers hash updated accordingly."); + // console.log("Browsers hash (window.location.hash) updated with [" + stateKeyValue + "]"); } else { - // console.log("Browsers hash already has the value of the state hash. Not - // updating browser hash."); + // console.log("Browsers hash (window.location.hash) already has the value [" + stateKeyValue + "]"); } }; }; @@ -173,13 +182,12 @@ var ActiveclientsRecordListener = function() { this.invoke = function(field) { var updateDoc = StringtoXML(field.textContent || field.text); var activeClientsRecordValue = (updateDoc.childNodes[0].textContent || updateDoc.childNodes[0].text); - console.log('Activeclients response for record detected: ' - + activeClientsRecordValue); + // console.log('Activeclients response for record detected: ' + activeClientsRecordValue); clearTimeout(renderOnRecordTargetsReqVar); if (activeClientsRecordValue > '0') { renderOnRecordTargets(true); } else { - console.log('Active clients is 0, final rendering'); + // console.log('Active clients is 0, final rendering'); renderOnRecordTargets(false); } }; diff --git a/src/META-INF/resources/pz2utils/pz2watch.xhtml b/src/META-INF/resources/pz2utils/pz2watch.xhtml index 0ca45f9..b681b98 100644 --- a/src/META-INF/resources/pz2utils/pz2watch.xhtml +++ b/src/META-INF/resources/pz2utils/pz2watch.xhtml @@ -38,7 +38,7 @@ - + diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java b/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java index 4c31b96..30ac455 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java @@ -140,9 +140,12 @@ public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Seria logger.debug("Ignoring record request due search error."); return ""; } else { + logger.debug("Executing record command"); ResponseDataObject responseObject = doCommand("record"); - if (pzreq.getRecord().hasParameterValue("offset") || - pzreq.getRecord().hasParameterValue("checksum")) { + if ((pzreq.getRecord().hasParameterValue("offset") || + pzreq.getRecord().hasParameterValue("checksum")) && + !responseObject.getType().equals("record")) { + logger.debug("Storing record offset response as 'record'"); RecordResponse recordResponse = new RecordResponse(); recordResponse.setType("record"); recordResponse.setXml(responseObject.getXml()); @@ -288,7 +291,19 @@ public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Seria pager = new ResultsPager(pzresp,pageRange,pzreq); return pager; } - + + /** + * This methods main purpose is to support browser history. + * + * When the browsers back or forward buttons are pressed, a + * re-search /might/ be required - namely if the query changes. + * So, as the UI requests updates of the page (show,facets, + * etc) this method checks if a search must be executed + * before those updates are performed. + * + * @see {@link com.indexdata.mkjsf.pazpar2.state.StateManager#setCurrentStateKey} + * @param commands + */ protected void handleQueryStateChanges (String commands) { if (stateMgr.hasPendingStateChange("search") && hasQuery()) { logger.info("Triggered search: Found pending search change [" + pzreq.getCommand("search").toString() + "], doing search before updating " + commands); @@ -323,8 +338,11 @@ public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Seria responseLogger.debug("Response was: " + commandResponse.getResponseString()); responseObject = ResponseParser.getParser().getDataObject((ClientCommandResponse)commandResponse); if (ResponseParser.docTypes.contains(responseObject.getType())) { + logger.debug("Storing " + responseObject.getType() + " in pzresp. "); pzresp.put(commandName, responseObject); - } + } else { + logger.info("Unrecognized response object type not cached in pzresp: " + responseObject.getType()); + } return responseObject; } diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/data/RecordResponse.java b/src/main/java/com/indexdata/mkjsf/pazpar2/data/RecordResponse.java index d3607c1..048b75d 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/data/RecordResponse.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/data/RecordResponse.java @@ -62,8 +62,9 @@ public class RecordResponse extends ResponseDataObject { } public String getActiveClients () { - logger.info("Request to get activeclients"); - return getOneElementValue("activeclients"); + String activeclients = getOneElementValue("activeclients"); + logger.info("Request to get activeclients on record [" + getRecId() + "]. Is [" + activeclients + "]"); + return activeclients; } } diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/state/StateManager.java b/src/main/java/com/indexdata/mkjsf/pazpar2/state/StateManager.java index d185559..04c9c3f 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/state/StateManager.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/state/StateManager.java @@ -12,7 +12,6 @@ import javax.enterprise.context.SessionScoped; import org.apache.log4j.Logger; import com.indexdata.mkjsf.pazpar2.commands.Pazpar2Command; -import com.indexdata.mkjsf.pazpar2.commands.sp.AuthCommand; import com.indexdata.mkjsf.utils.Utils; @SessionScoped @@ -90,33 +89,45 @@ public class StateManager implements Serializable { * Changes the current state key. Invoked from the UI to have the state * manager switch to another state than the current one. * + * @See The state field in pz2watch.xhtml
+ * The state listeners windowlocationhashListener() and StateListener() + * in listeners.js
+ * The method {@link com.indexdata.mkjsf.pazpar2.Pz2Bean#handleQueryStateChanges}
+ * The class {@link com.indexdata.mkjsf.pazpar2.state.Pazpar2State}
+ * ... for a complete picture of browser history handling. + * * @param key */ public void setCurrentStateKey(String key) { if (currentKey.equals(key)) { - logger.debug("setCurrentStateKey: no key change detected"); + logger.debug("Ignoring request from UI to set state key, already has that key [" + key + "]"); } else { - logger.debug("State key change. Was: [" + currentKey + "]. Will be ["+key+"]"); + logger.debug("Request from UI to change state key from: [" + currentKey + "] to ["+key+"]"); if (states.get(key)==null) { - logger.error("The back-end received an unknow state key, probably UI generated: ["+ key +"]."); + logger.error("Have no state registered for the key ["+ key +"]."); if (key == null || key.length()==0) { - logger.info("Empty key received, treating it as identical to current key going forward."); + logger.info("Recived an empty key, retaining currentKey [" + currentKey + "]"); key = currentKey; } else { if (states.get(currentKey) != null) { - logger.info("Current search state cached under both of [" + key + "] and [" + currentKey + "]"); - states.put(key,states.get(currentKey)); + if (key.equals("#1")) { + logger.info("Initial key created [" + key + "], but already got a state registered for the current key [" + currentKey + "]. Retaining current key."); + key = currentKey; + } else { + logger.info("Current search state cached under both new key [" + key + "] and current key [" + currentKey + "]"); + states.put(key,states.get(currentKey)); + } } } } if (states.get(key).getCommand("search").equals(states.get(currentKey).getCommand("search"))) { - logger.debug("No search change detected"); + logger.debug("No search change detected as a consequence of processing the key ["+key+"]"); } else { hasPendingStateChange("search",true); } if (states.get(key).getCommand("record").equals(states.get(currentKey).getCommand("record"))) { - logger.debug("No record change detected"); + logger.debug("No record change detected as a consequence of processing the key ["+key+"]"); } else { hasPendingStateChange("record",true); } -- 1.7.10.4