X-Git-Url: http://lists.indexdata.dk/cgi-bin?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fcom%2Findexdata%2Fmkjsf%2Fpazpar2%2FPz2Service.java;h=8b86fd6faad35fb3c9e99c8bae649bdb3a09920d;hb=5211ca6a4525491499ac763373a703e35bdce37f;hp=f38d90db49e4109637fa27b08ecded61c7ed840a;hpb=45780ca51a3f1a967acda7c4d7d71aebe7081a67;p=mkjsf-moved-to-github.git diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Service.java b/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Service.java index f38d90d..8b86fd6 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Service.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Service.java @@ -28,17 +28,47 @@ import com.indexdata.mkjsf.errors.ConfigurationError; import com.indexdata.mkjsf.errors.ConfigurationException; import com.indexdata.mkjsf.errors.ErrorCentral; import com.indexdata.mkjsf.errors.ErrorHelper; -import com.indexdata.mkjsf.pazpar2.commands.Pazpar2Command; +import com.indexdata.mkjsf.errors.MissingConfigurationContextException; import com.indexdata.mkjsf.pazpar2.commands.Pazpar2Commands; import com.indexdata.mkjsf.pazpar2.data.RecordResponse; -import com.indexdata.mkjsf.pazpar2.data.ResponseDataObject; import com.indexdata.mkjsf.pazpar2.data.Responses; import com.indexdata.mkjsf.pazpar2.state.StateListener; import com.indexdata.mkjsf.pazpar2.state.StateManager; import com.indexdata.mkjsf.utils.Utils; +/** + * Pz2Service is the main controller of the search logic, used for selecting the service + * type (which can be done by configuration and/or run-time), selecting which search client + * to use, and performing high-level control of request cycles and state management. + *
+ * Command and response beans are also obtained through Pz2Service - although it is + * transparent to the UI that they are retrieved through this object. + *
+ *
+ * Pz2Service is exposed to the UI as pz2
. However, if the service is pre-configured,
+ * the Faces pages might never need to reference pz2
explicitly. Indirectly they will,
+ * though, if the polling mechanism in the tag <pz2utils:pz2watch>
is used.
+ *
+ *
+ *
When configuring the client using the Mk2Config scheme, this is the prefix to + * use in the .properties file. When using web.xml context parameters for configuration + * the configuration name has no effect.
+ * + *Pz2Service will acknowledge following configuration parameters: + * + *
+ * If there are outstanding changes to the search command, a search + * will be issued before the updates are performed. Outstanding changes could come + * from the UI changing a search parameter and not executing search before starting + * the update cycle - OR - it could come from the user clicking the browsers back/forward + * buttons. + *
+ *+ * This method is invoked from the composite 'pz2watch', which uses Ajax + * to keep invoking this method until it returns '0' (for zero active clients). + *
+ *+ * UI components that display data from show, stat, termlist or bytarget, + * should be re-rendered after each update. + *
+ * Example of invocation in UI: + *+ * <pz2utils:pz2watch id="pz2watch" + * renderWhileActiveclients="myshowui mystatui mytermsui" /< + * + * <h:form> + * <h:inputText id="query" value="#{pzreq.search.query}" size="50"/> + * <h:commandButton id="button" value="Search"> + * <f:ajax execute="query" render="${pz2.watchActiveclients}"/> + * </h:commandButton> + * </h:form> + *+ * The expression pz2.watchActiveClients will invoke the method repeatedly, and the + * UI sections myshowui, mystatui, and mytermsui will be rendered on each poll. * - * @return Number of activeclients at the time of the 'show' command. - */ + * @return a count of the remaining active clients from the most recent search. + */ public String update () { logger.debug("Updating show,stat,termlist,bytarget from pazpar2"); if (errors.hasConfigurationErrors()) { @@ -168,9 +245,11 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se } /** - * Refreshes the data objects listed in 'commands' from pazpar2 + * Simultaneously refreshes the data objects listed in 'commands' from pazpar2, potentially running a + * search or a record command first if any of these two commands have outstanding parameter changes. + * + * @param commands, a comma-separated list of Pazpar2 commands to execute * - * @param commands * @return Number of activeclients at the time of the 'show' command, * or 'new' if search was just initiated. */ @@ -179,6 +258,7 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se try { if (commands.equals("search")) { pzreq.getSearch().run(); + pzresp.getSearch().setIsNew(false); return "new"; } else if (commands.equals("record")) { pzreq.getRecord().run(); @@ -228,7 +308,59 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se } } - + + /** + * 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. + * + * It will consequently also run a search if the UI updates a + * search parameter without actually explicitly executing the search + * before setting of the polling. + * + * @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); + pzreq.getSearch().run(); + pzresp.getSearch().setIsNew(false); + } + if (stateMgr.hasPendingStateChange("record") && ! commands.equals("record")) { + logger.debug("Found pending record ID change. Doing record before updating " + commands); + stateMgr.hasPendingStateChange("record",false); + pzreq.getRecord().run(); + } + } + + /** + * Used by the state manager to notify Pz2Service about state changes + */ + @Override + public void stateUpdated(String commandName) { + logger.debug("State change reported for [" + commandName + "]"); + if (commandName.equals("show")) { + logger.debug("Updating show"); + update(commandName); + } + } + + + /** + * Will retrieve -- or alternatively remove -- the record with the given + * recid from memory. + * + * A pazpar2 'record' command will then be issued. The part of the UI + * showing record data should thus be re-rendered. + * + * @param recid + * @return + */ public String toggleRecord (String recId) { if (hasRecord(recId)) { pzreq.getRecord().removeParameters(); @@ -236,20 +368,39 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se return ""; } else { pzreq.getRecord().setId(recId); - doCommand("record"); + pzreq.getRecord().run(); return pzresp.getRecord().getActiveClients(); } } - @Override + /** + * Resolves whether the back-end has a record with the given recid in memory + * + * @return true if the bean currently holds the record with recid + */ public boolean hasRecord (String recId) { return pzreq.getCommand("record").hasParameters() && pzresp.getRecord().getRecId().equals(recId); } + /** + * Returns the current hash key, used for internal session state tracking + * and potentially for browser history entries + * + * A UI author would not normally be concerned with retrieving this. It's used by the + * framework internally + * + * @return string that can be used for browsers window.location.hash + */ public String getCurrentStateKey () { return stateMgr.getCurrentState().getKey(); } + /** + * Sets the current state key, i.e. when user clicks back or forward in browser history. + * Would normally be automatically handled by the frameworks components. + * + * @param key corresponding to browsers hash string + */ public void setCurrentStateKey(String key) { stateMgr.setCurrentStateKey(key); } @@ -258,8 +409,10 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se return pzreq.getCommand("search").hasParameterValue("query"); } - - @Override + /** + * Returns a component for drawing a pager to navigate by. + * @return ResultsPager pager component + */ public ResultsPager getPager () { if (pager == null) { pager = new ResultsPager(pzresp); @@ -267,73 +420,33 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se return pager; } - @Override + /** + * Initiates a pager object, a component holding the data to draw a sequence + * of page numbers to navigate by and mechanisms to navigate with + * + * @param pageRange number of pages to display in the pager + * @return ResultsPager the initiated pager component + */ public ResultsPager setPager (int pageRange) { 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); - pzreq.getSearch().run(); - } - if (stateMgr.hasPendingStateChange("record") && ! commands.equals("record")) { - logger.debug("Found pending record ID change. Doing record before updating " + commands); - stateMgr.hasPendingStateChange("record",false); - pzreq.getRecord().run(); - } - } - + /** - * Executes the command and parses the response to create data objects. - * If the parsed response is of a known type it will be cached in 'pzresp' + * Sets the URL of the Service Proxy to use for requests * - * @param commandName The command to be executed - * @return An XML response parsed to form a response data object + * @param url */ - protected ResponseDataObject doCommand(String commandName) { - Pazpar2Command command = pzreq.getCommand(commandName); - if (command.spOnly() && isPazpar2Service()) { - logger.warn("Skipping " + commandName + " - SP-only command, not supported by Pazpar2"); - return new ResponseDataObject(); - } else { - logger.info("Request "+commandName + ". Search command is: "+ pzreq.getCommand("search").toString()); - long start = System.currentTimeMillis(); - ResponseDataObject responseObject = command.run(); - long end = System.currentTimeMillis(); - logger.debug("Executed " + command.getCommandName() + " in " + (end-start) + " ms." ); - return responseObject; - } - } - - @Override - public void stateUpdated(String commandName) { - logger.debug("State change reported for [" + commandName + "]"); - if (commandName.equals("show")) { - logger.debug("Updating show"); - update(commandName); - } - } - public void setServiceProxyUrl(String url) { searchClient = spClient; setServiceType(SERVICE_TYPE_SP); setServiceUrl(url); } + /** + * Returns the Service Proxy URL currently defined for servicing requests + * + */ public String getServiceProxyUrl () { if (isServiceProxyService()) { return spClient.getServiceUrl(); @@ -341,13 +454,22 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se return ""; } } - + + /** + * Sets the URL of the Pazpar2 to use for requests + * + * @param url + */ public void setPazpar2Url(String url) { searchClient = pz2Client; setServiceType(SERVICE_TYPE_PZ2); setServiceUrl(url); } + /** + * Returns the Pazpar2 URL currently defined for servicing requests + * + */ public String getPazpar2Url() { if (isPazpar2Service()) { return pz2Client.getServiceUrl(); @@ -356,8 +478,12 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se } } - - @Override + /** + * Sets the URL to be used by the currently selected search client + * when running requests. + * + * @param url + */ public void setServiceUrl(String url) { if (url!=null && searchClient != null && !url.equals(searchClient.getServiceUrl())) { pzreq.getRecord().removeParametersInState(); @@ -367,6 +493,10 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se } } + /** + * Gets the currently selected URL used for executing requests. + * @return + */ public String getServiceUrl() { return (searchClient!=null ? searchClient.getServiceUrl() : ""); } @@ -420,22 +550,18 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se return spClient; } - @Override public boolean getAuthenticationRequired () { return spClient.isAuthenticatingClient(); } - @Override public String getCheckHistory () { return ":pz2watch:stateForm:windowlocationhash"; } - @Override public String getWatchActiveclients () { return ":pz2watch:activeclientsForm:activeclientsField"; } - @Override public String getWatchActiveclientsRecord () { return ":pz2watch:activeclientsForm:activeclientsFieldRecord"; } @@ -479,19 +605,16 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se return new ArrayList