Disentangles update() logic. Adds option for early feedback.
authorNiels Erik G. Nielsen <nielserik@indexdata.com>
Mon, 13 May 2013 18:36:05 +0000 (14:36 -0400)
committerNiels Erik G. Nielsen <nielserik@indexdata.com>
Mon, 13 May 2013 18:36:05 +0000 (14:36 -0400)
'search' and 'record' commands are disentangled from the general update()
logic, in particular there is no longer recursion into update() in cases
where a 'search' is needed before a 'show', say. Dedicated doSearch and
doRecord methods are added with the intention of clarifying things.

Also adds an option for feedback right after 'search' returns, by having
update(show,stat,bytarget,termlist) skip processing on the first
round-trip. The UI thus have a change to detect that a search has started
and notify the user (before it would need to wait for the first update of
show,stat,.. etc). For setups with dozens or even hundreds of targets the
wait for the first sign of activity can otherwise be many seconds.

src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java
src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Interface.java
src/main/java/com/indexdata/mkjsf/pazpar2/data/SearchResponse.java

index 16abd12..d7a9235 100644 (file)
@@ -24,6 +24,7 @@ import com.indexdata.mkjsf.errors.ConfigurationException;
 import com.indexdata.mkjsf.errors.ErrorCentral;\r
 import com.indexdata.mkjsf.errors.ErrorHelper;\r
 import com.indexdata.mkjsf.pazpar2.commands.CommandParameter;\r
+import com.indexdata.mkjsf.pazpar2.commands.Pazpar2Command;\r
 import com.indexdata.mkjsf.pazpar2.commands.Pazpar2Commands;\r
 import com.indexdata.mkjsf.pazpar2.data.RecordResponse;\r
 import com.indexdata.mkjsf.pazpar2.data.ResponseDataObject;\r
@@ -118,7 +119,20 @@ public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Seria
     pzreq.getRecord().removeParametersInState();        \r
     pzreq.getShow().setParameterInState(new CommandParameter("start","=",0));    \r
     logger.debug(Utils.objectId(this) + " is searching using "+pzreq.getCommand("search").getUrlEncodedParameterValue("query"));\r
-    doCommand("search");    \r
+    doCommand("search");      \r
+  }\r
+  \r
+  public String doRecord() {\r
+    ResponseDataObject responseObject = doCommand("record");\r
+    if (pzreq.getRecord().hasParameterValue("offset") ||\r
+          pzreq.getRecord().hasParameterValue("checksum")) {\r
+        RecordResponse recordResponse = new RecordResponse();\r
+        recordResponse.setType("record");\r
+        recordResponse.setXml(responseObject.getXml());\r
+        recordResponse.setAttribute("activeclients", "0");\r
+        pzresp.put("record", recordResponse);\r
+     }\r
+     return pzresp.getRecord().getActiveClients();    \r
   }\r
       \r
   /**\r
@@ -160,15 +174,25 @@ public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Seria
   public String update (String commands) {\r
     logger.info("Request to update: " + commands);\r
     try {\r
-      if (! validateUpdateRequest(commands)) {\r
+      if (!validateUpdateRequest(commands)) {\r
         return "0";\r
+      } else if (commands.equals("search")) {\r
+        doSearch();\r
+        return "";\r
+      } else if (commands.equals("record")) {\r
+        return doRecord();\r
+      } else if (pzresp.getSearch().isNew()) {\r
+        logger.info("New search. Marking it old, then returning 'new' to trigger another round-trip.");\r
+        pzresp.getSearch().setIsNew(false);\r
+        return "new";\r
       } else {\r
         handleQueryStateChanges(commands);\r
-        if (!commands.equals("search") && pzresp.getSearch().hasApplicationError()) {\r
+        if (pzresp.getSearch().hasApplicationError()) {\r
           logger.error("The command(s) " + commands + " are cancelled because the latest search command had an error.");\r
           return "0";\r
         } else {\r
           logger.debug("Processing request for " + commands); \r
+          \r
           List<CommandThread> threadList = new ArrayList<CommandThread>();\r
           StringTokenizer tokens = new StringTokenizer(commands,",");\r
           while (tokens.hasMoreElements()) {          \r
@@ -192,22 +216,10 @@ public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Seria
              if (ResponseParser.docTypes.contains(responseObject.getType())) {\r
                pzresp.put(commandName, responseObject);\r
              } else {\r
-               if (commandName.equals("record") && \r
-                   (pzreq.getRecord().hasParameterValue("offset") ||\r
-                    pzreq.getRecord().hasParameterValue("checksum"))) {\r
-                 RecordResponse recordResponse = new RecordResponse();\r
-                 recordResponse.setType("record");\r
-                 recordResponse.setXml(responseObject.getXml());\r
-                 recordResponse.setAttribute("activeclients", "0");\r
-                 pzresp.put(commandName, recordResponse);\r
-               }\r
+               logger.info("Unknown doc type [" + responseObject.getType() + "]. Was not cached.");\r
              }\r
           }\r
-          if (commands.equals("record")) {\r
-            return pzresp.getRecord().getActiveClients();\r
-          } else {\r
-            return pzresp.getActiveClients();\r
-          }\r
+          return pzresp.getActiveClients();\r
         }\r
       }  \r
     } catch (ClassCastException cce) {\r
@@ -240,7 +252,8 @@ public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Seria
       return "";\r
     } else {\r
       pzreq.getRecord().setId(recId);\r
-      return doCommand("record");\r
+      doCommand("record");\r
+      return pzresp.getRecord().getActiveClients();\r
     }\r
   }\r
   \r
@@ -285,18 +298,38 @@ public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Seria
       logger.debug("Found pending record ID change. Doing record before updating " + commands);\r
       stateMgr.hasPendingStateChange("record",false);\r
       if (pzreq.getCommand("record").hasParameterValue("id")) {\r
-        update("record");\r
+        doRecord();\r
       } else {         \r
         pzresp.put("record", new RecordResponse());\r
       }\r
     }\r
   }\r
   \r
-  protected String doCommand(String commandName) {             \r
-    logger.debug(pzreq.getCommand(commandName).getEncodedQueryString() + ": Results for "+ pzreq.getCommand("search").getEncodedQueryString());\r
-    return update(commandName);\r
+  /**\r
+   * Validates the request then executes the command and parses the response.\r
+   * If the parsed response is of a known type it will be cached in 'pzresp'\r
+   * \r
+   * @param commandName The command to be executed\r
+   * @return An XML response parsed to form a response data object\r
+   */\r
+  protected ResponseDataObject doCommand(String commandName) {\r
+    ResponseDataObject responseObject = null; \r
+    if (validateUpdateRequest(commandName)) {\r
+      logger.debug(pzreq.getCommand(commandName).getEncodedQueryString() + ": Results for "+ pzreq.getCommand("search").getEncodedQueryString());\r
+      Pazpar2Command command = pzreq.getCommand(commandName);\r
+      long start = System.currentTimeMillis();\r
+      HttpResponseWrapper commandResponse = searchClient.executeCommand(command);\r
+      long end = System.currentTimeMillis();\r
+      logger.debug("Executed " + command.getCommandName() + " in " + (end-start) + " ms." );\r
+      responseLogger.debug("Response was: " + commandResponse.getResponseString());\r
+      responseObject = ResponseParser.getParser().getDataObject((ClientCommandResponse)commandResponse);\r
+      if (ResponseParser.docTypes.contains(responseObject.getType())) {\r
+        pzresp.put(commandName, responseObject);\r
+      }      \r
+    }\r
+    return responseObject;\r
   }\r
-  \r
+    \r
   @Override\r
   public void stateUpdated(String commandName) {\r
     logger.debug("State change reported for [" + commandName + "]");\r
index 7b0b863..b8b6d24 100644 (file)
@@ -19,6 +19,12 @@ public interface Pz2Interface extends Serializable {
   public void doSearch();\r
   \r
   /**\r
+   * Executes a Pazpar2 record requests\r
+   * @return Active clients for the record request\r
+   */\r
+  public String doRecord();\r
+  \r
+  /**\r
    * Updates display data objects by issuing the following pazpar2 commands: \r
    * 'show', 'stat', 'termlist' and 'bytarget'.\r
    *  \r
index 909e05b..c905c26 100644 (file)
@@ -3,9 +3,18 @@ package com.indexdata.mkjsf.pazpar2.data;
 public class SearchResponse extends ResponseDataObject {\r
 \r
   private static final long serialVersionUID = -3320013021497018972L;\r
+  private boolean isNew = true;\r
   \r
   public String getStatus() {\r
     return getOneElementValue("status");\r
   }\r
+  \r
+  public boolean isNew () {\r
+    return isNew; \r
+  }\r
+  \r
+  public void setIsNew (boolean isNew) {\r
+    this.isNew = isNew;\r
+  }\r
 \r
 }\r