X-Git-Url: http://lists.indexdata.dk/cgi-bin?a=blobdiff_plain;ds=inline;f=src%2Fmain%2Fjava%2Fcom%2Findexdata%2Fmkjsf%2Fpazpar2%2FPz2Service.java;h=4d6d05fe14a4284141d2bfdab4d058f35022fd19;hb=86f289cd42ba95846c80d22129ed565e4e9d6dde;hp=f38d90db49e4109637fa27b08ecded61c7ed840a;hpb=9cd922c29f423b69da6f52eabf0c7fdb0b0b6ca5;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..4d6d05f 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Service.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Service.java @@ -28,17 +28,31 @@ 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
+ * 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.
+ * 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.
+ *
+ *
+ **/
@Named("pz2") @SessionScoped
-public class Pz2Service implements Pz2Interface, StateListener, Configurable, Serializable {
+public class Pz2Service implements StateListener, Configurable, Serializable {
private static final String MODULE_NAME = "service";
private static String SERVICE_TYPE_TBD = "TBD", SERVICE_TYPE_PZ2 = "PZ2", SERVICE_TYPE_SP = "SP";
@@ -50,9 +64,8 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se
private List
+ * <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 +229,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 +242,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 +292,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 +352,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 +393,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 +404,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 +438,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 +462,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 +477,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 +534,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,17 +589,14 @@ public class Pz2Service implements Pz2Interface, StateListener, Configurable, Se
return new ArrayList