1 package com.indexdata.mkjsf.pazpar2;
\r
3 import java.io.Serializable;
\r
4 import java.util.ArrayList;
\r
5 import java.util.Arrays;
\r
6 import java.util.HashMap;
\r
7 import java.util.List;
\r
8 import java.util.Map;
\r
9 import java.util.StringTokenizer;
\r
11 import javax.annotation.PostConstruct;
\r
12 import javax.enterprise.context.SessionScoped;
\r
13 import javax.inject.Inject;
\r
14 import javax.inject.Named;
\r
16 import org.apache.log4j.Logger;
\r
18 import com.indexdata.mkjsf.config.Configurable;
\r
19 import com.indexdata.mkjsf.config.Configuration;
\r
20 import com.indexdata.mkjsf.config.ConfigurationReader;
\r
21 import com.indexdata.mkjsf.controls.ResultsPager;
\r
22 import com.indexdata.mkjsf.errors.ConfigurationError;
\r
23 import com.indexdata.mkjsf.errors.ConfigurationException;
\r
24 import com.indexdata.mkjsf.errors.ErrorCentral;
\r
25 import com.indexdata.mkjsf.errors.ErrorHelper;
\r
26 import com.indexdata.mkjsf.pazpar2.commands.CommandParameter;
\r
27 import com.indexdata.mkjsf.pazpar2.commands.Pazpar2Commands;
\r
28 import com.indexdata.mkjsf.pazpar2.data.RecordResponse;
\r
29 import com.indexdata.mkjsf.pazpar2.data.ResponseDataObject;
\r
30 import com.indexdata.mkjsf.pazpar2.data.ResponseParser;
\r
31 import com.indexdata.mkjsf.pazpar2.data.Responses;
\r
32 import com.indexdata.mkjsf.pazpar2.sp.auth.ServiceProxyUser;
\r
33 import com.indexdata.mkjsf.pazpar2.state.StateListener;
\r
34 import com.indexdata.mkjsf.pazpar2.state.StateManager;
\r
35 import com.indexdata.mkjsf.utils.Utils;
\r
37 @Named("pz2") @SessionScoped
\r
38 public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Serializable {
\r
40 private static final String MODULE_NAME = "service";
\r
41 private static String SERVICE_TYPE_TBD = "TBD", SERVICE_TYPE_PZ2 = "PZ2", SERVICE_TYPE_SP = "SP";
\r
42 private static final List<String> serviceTypes =
\r
43 Arrays.asList(SERVICE_TYPE_PZ2,SERVICE_TYPE_SP,SERVICE_TYPE_TBD);
\r
44 private String serviceType = SERVICE_TYPE_TBD;
\r
45 private List<String> serviceProxyUrls = new ArrayList<String>();
\r
46 public static final String SERVICE_PROXY_URL_LIST = "SERVICE_PROXY_URL_LIST";
\r
47 private List<String> pazpar2Urls = new ArrayList<String>();
\r
48 public static final String PAZPAR2_URL_LIST = "PAZPAR2_URL_LIST";
\r
51 private static final long serialVersionUID = 3440277287081557861L;
\r
52 private static Logger logger = Logger.getLogger(Pz2Bean.class);
\r
53 private static Logger responseLogger = Logger.getLogger("com.indexdata.mkjsf.pazpar2.responses");
\r
54 protected Pz2Client pz2Client = null;
\r
55 protected ServiceProxyClient spClient = null;
\r
56 protected SearchClient searchClient = null;
\r
58 @Inject ConfigurationReader configurator;
\r
59 @Inject StateManager stateMgr;
\r
60 @Inject Pazpar2Commands pzreq;
\r
61 @Inject Responses pzresp;
\r
62 @Inject ErrorCentral errors;
\r
63 @Inject ServiceProxyUser user;
\r
65 protected ResultsPager pager = null;
\r
67 protected ErrorHelper errorHelper = null;
\r
70 logger.info("Instantiating pz2 bean [" + Utils.objectId(this) + "]");
\r
74 public void postConstruct() {
\r
75 logger.debug("Pz2Bean post-construct: Configurator is " + configurator);
\r
76 logger.debug(Utils.objectId(this) + " will instantiate a Pz2Client next.");
\r
77 pz2Client = new Pz2Client();
\r
78 configureClient(pz2Client,configurator);
\r
79 spClient = new ServiceProxyClient();
\r
80 configureClient(spClient,configurator);
\r
82 this.configure(configurator);
\r
83 } catch (ConfigurationException e) {
\r
84 logger.error("There was a problem configuring the Pz2Bean (\"pz2\")");
\r
85 e.printStackTrace();
\r
87 stateMgr.addStateListener(this);
\r
90 public void configureClient(SearchClient client, ConfigurationReader configReader) {
\r
91 logger.debug(Utils.objectId(this) + " will configure search client for the session");
\r
93 client.configure(configReader);
\r
94 } catch (ConfigurationException e) {
\r
95 logger.debug("Pz2Bean adding configuration error");
\r
96 errors.addConfigurationError(new ConfigurationError("Search Client","Configuration",e.getMessage()));
\r
98 logger.info(configReader.document());
\r
99 pzresp.resetAllSessionData();
\r
102 public void resetSearchAndRecordCommands () {
\r
103 pzreq.getRecord().removeParametersInState();
\r
104 pzreq.getSearch().removeParametersInState();
\r
108 public void doSearch(String query) {
\r
109 pzreq.getSearch().setParameter(new CommandParameter("query","=",query));
\r
113 public void doSearch() {
\r
114 stateMgr.hasPendingStateChange("search",false);
\r
115 pzresp.resetSearchResponses();
\r
116 // resets some record and show command parameters without
\r
117 // changing state or creating state change feedback
\r
118 pzreq.getRecord().removeParametersInState();
\r
119 pzreq.getShow().setParameterInState(new CommandParameter("start","=",0));
\r
120 logger.debug(Utils.objectId(this) + " is searching using "+pzreq.getCommand("search").getUrlEncodedParameterValue("query"));
\r
121 doCommand("search");
\r
125 * Refreshes 'show', 'stat', 'termlist', and 'bytarget' data object from pazpar2
\r
127 * @return Number of activeclients at the time of the 'show' command.
\r
129 public String update () {
\r
130 logger.debug("Updating show,stat,termlist,bytarget from pazpar2");
\r
131 return update("show,stat,termlist,bytarget");
\r
134 public boolean validateUpdateRequest(String commands) {
\r
135 if (errors.hasConfigurationErrors()) {
\r
136 logger.error("The command(s) " + commands + " are cancelled due to configuration errors.");
\r
138 } else if (!commands.equals("search") && pzresp.getSearch().hasApplicationError()) {
\r
139 logger.error("The command(s) " + commands + " are cancelled because the latest search command had an error.");
\r
141 } else if (!commandsAreValid(commands)) {
\r
142 logger.debug("The command(s) " + commands + " are cancelled because the were not found to be ready/valid.");
\r
144 } else if (!hasQuery() && !(commands.equals("record") && pzreq.getCommand("record").hasParameterValue("recordquery"))) {
\r
145 logger.debug("The command(s) " + commands + " are held off because there's not yet a query.");
\r
155 * Refreshes the data objects listed in 'commands' from pazpar2
\r
158 * @return Number of activeclients at the time of the 'show' command
\r
160 public String update (String commands) {
\r
161 logger.info("Request to update: " + commands);
\r
163 if (! validateUpdateRequest(commands)) {
\r
166 handleQueryStateChanges(commands);
\r
167 if (! validateUpdateRequest(commands)) {
\r
170 logger.debug("Processing request for " + commands);
\r
171 List<CommandThread> threadList = new ArrayList<CommandThread>();
\r
172 StringTokenizer tokens = new StringTokenizer(commands,",");
\r
173 while (tokens.hasMoreElements()) {
\r
174 threadList.add(new CommandThread(pzreq.getCommand(tokens.nextToken()),searchClient));
\r
176 for (CommandThread thread : threadList) {
\r
179 for (CommandThread thread : threadList) {
\r
182 } catch (InterruptedException e) {
\r
183 e.printStackTrace();
\r
186 for (CommandThread thread : threadList) {
\r
187 String commandName = thread.getCommand().getCommandName();
\r
188 ClientCommandResponse response = (ClientCommandResponse) thread.getCommandResponse();
\r
189 responseLogger.debug("Response was: " + response.getResponseString());
\r
190 ResponseDataObject responseObject = ResponseParser.getParser().getDataObject(response);
\r
191 if (ResponseParser.docTypes.contains(responseObject.getType())) {
\r
192 pzresp.put(commandName, responseObject);
\r
194 if (commandName.equals("record") &&
\r
195 (pzreq.getRecord().hasParameterValue("offset") ||
\r
196 pzreq.getRecord().hasParameterValue("checksum"))) {
\r
197 RecordResponse recordResponse = new RecordResponse();
\r
198 recordResponse.setType("record");
\r
199 recordResponse.setXml(responseObject.getXml());
\r
200 recordResponse.setAttribute("activeclients", "0");
\r
201 pzresp.put(commandName, recordResponse);
\r
205 if (commands.equals("record")) {
\r
206 return pzresp.getRecord().getActiveClients();
\r
208 return pzresp.getActiveClients();
\r
212 } catch (ClassCastException cce) {
\r
213 cce.printStackTrace();
\r
215 } catch (NullPointerException npe) {
\r
216 npe.printStackTrace();
\r
218 } catch (Exception e) {
\r
219 e.printStackTrace();
\r
225 public boolean commandsAreValid(String commands) {
\r
226 if (commands.equals("record")) {
\r
227 if (!pzreq.getCommand("record").hasParameterValue("id")) {
\r
228 logger.debug("Skips sending record command due to lacking id parameter");
\r
235 public String toggleRecord (String recId) {
\r
236 if (hasRecord(recId)) {
\r
237 pzreq.getRecord().removeParameters();
\r
238 pzresp.put("record", new RecordResponse());
\r
241 pzreq.getRecord().setId(recId);
\r
242 return doCommand("record");
\r
247 public boolean hasRecord (String recId) {
\r
248 return pzreq.getCommand("record").hasParameters() && pzresp.getRecord().getRecId().equals(recId);
\r
251 public String getCurrentStateKey () {
\r
252 return stateMgr.getCurrentState().getKey();
\r
255 public void setCurrentStateKey(String key) {
\r
256 stateMgr.setCurrentStateKey(key);
\r
259 protected boolean hasQuery() {
\r
260 return pzreq.getCommand("search").hasParameterValue("query");
\r
265 public ResultsPager getPager () {
\r
266 if (pager == null) {
\r
267 pager = new ResultsPager(pzresp);
\r
273 public ResultsPager setPager (int pageRange) {
\r
274 pager = new ResultsPager(pzresp,pageRange,pzreq);
\r
278 protected void handleQueryStateChanges (String commands) {
\r
279 if (stateMgr.hasPendingStateChange("search") && hasQuery()) {
\r
280 logger.info("Triggered search: Found pending search change, doing search before updating " + commands);
\r
283 if (stateMgr.hasPendingStateChange("record") && ! commands.equals("record")) {
\r
284 logger.debug("Found pending record ID change. Doing record before updating " + commands);
\r
285 stateMgr.hasPendingStateChange("record",false);
\r
286 if (pzreq.getCommand("record").hasParameterValue("id")) {
\r
289 pzresp.put("record", new RecordResponse());
\r
294 protected String doCommand(String commandName) {
\r
295 logger.debug(pzreq.getCommand(commandName).getEncodedQueryString() + ": Results for "+ pzreq.getCommand("search").getEncodedQueryString());
\r
296 return update(commandName);
\r
300 public void stateUpdated(String commandName) {
\r
301 logger.debug("State change reported for [" + commandName + "]");
\r
302 if (commandName.equals("show")) {
\r
303 logger.debug("Updating show");
\r
304 update(commandName);
\r
308 public void setServiceProxyUrl(String url) {
\r
309 searchClient = spClient;
\r
310 setServiceType(SERVICE_TYPE_SP);
\r
311 setServiceUrl(url);
\r
314 public String getServiceProxyUrl () {
\r
315 if (isServiceProxyService()) {
\r
316 return spClient.getServiceUrl();
\r
322 public void setPazpar2Url(String url) {
\r
323 searchClient = pz2Client;
\r
324 setServiceType(SERVICE_TYPE_PZ2);
\r
325 setServiceUrl(url);
\r
328 public String getPazpar2Url() {
\r
329 if (isPazpar2Service()) {
\r
330 return pz2Client.getServiceUrl();
\r
338 public void setServiceUrl(String url) {
\r
339 if (url!=null && searchClient != null && !url.equals(searchClient.getServiceUrl())) {
\r
340 pzreq.getRecord().removeParametersInState();
\r
341 pzreq.getSearch().removeParametersInState();
\r
342 pzresp.resetAllSessionData();
\r
344 searchClient.setServiceUrl(url);
\r
348 public String getServiceUrl() {
\r
349 return (searchClient!=null ? searchClient.getServiceUrl() : "");
\r
352 public boolean getServiceUrlIsDefined() {
\r
353 return (searchClient != null && searchClient.hasServiceUrl());
\r
356 public List<String> getServiceProxyUrls() {
\r
357 List<String> urls = new ArrayList<String>();
\r
359 urls.addAll(serviceProxyUrls);
\r
363 public List<String> getPazpar2Urls () {
\r
364 List<String> urls = new ArrayList<String>();
\r
366 urls.addAll(pazpar2Urls);
\r
370 public String getServiceType () {
\r
371 return serviceType;
\r
374 public boolean isPazpar2Service () {
\r
375 return serviceType.equals(SERVICE_TYPE_PZ2);
\r
378 public boolean isServiceProxyService() {
\r
379 return serviceType.equals(SERVICE_TYPE_SP);
\r
382 public boolean serviceIsToBeDecided () {
\r
383 return serviceType.equals(SERVICE_TYPE_TBD);
\r
386 public ServiceProxyClient getSpClient () {
\r
391 public boolean getAuthenticationRequired () {
\r
392 return spClient.isAuthenticatingClient();
\r
396 public String getCheckHistory () {
\r
397 return ":pz2watch:stateForm:windowlocationhash";
\r
401 public String getWatchActiveclients () {
\r
402 return ":pz2watch:activeclientsForm:activeclientsField";
\r
406 public String getWatchActiveclientsRecord () {
\r
407 return ":pz2watch:activeclientsForm:activeclientsFieldRecord";
\r
411 public void configure(ConfigurationReader reader)
\r
412 throws ConfigurationException {
\r
413 Configuration config = reader.getConfiguration(this);
\r
414 if (config == null) {
\r
415 serviceType = SERVICE_TYPE_TBD;
\r
417 String service = config.get("TYPE");
\r
418 if (service == null || service.length()==0) {
\r
419 serviceType = SERVICE_TYPE_TBD;
\r
420 } else if (serviceTypes.contains(service.toUpperCase())) {
\r
421 setServiceType(service.toUpperCase());
\r
423 logger.error("Unknown serviceType type in configuration [" + service + "], can be one of " + serviceTypes);
\r
424 serviceType = SERVICE_TYPE_TBD;
\r
426 serviceProxyUrls = config.getMultiProperty(SERVICE_PROXY_URL_LIST,",");
\r
427 pazpar2Urls = config.getMultiProperty(PAZPAR2_URL_LIST, ",");
\r
429 logger.info("Service Type is configured to " + serviceType);
\r
434 public Map<String, String> getDefaults() {
\r
435 return new HashMap<String,String>();
\r
439 public String getModuleName() {
\r
440 return MODULE_NAME;
\r
444 public List<String> documentConfiguration() {
\r
445 return new ArrayList<String>();
\r
449 public void setServiceTypePZ2() {
\r
450 setServiceType(SERVICE_TYPE_PZ2);
\r
454 public void setServiceTypeSP() {
\r
455 setServiceType(SERVICE_TYPE_SP);
\r
459 public void setServiceTypeTBD() {
\r
460 setServiceType(SERVICE_TYPE_TBD);
\r
463 private void setServiceType(String type) {
\r
464 if (!serviceType.equals(type) &&
\r
465 !serviceType.equals(SERVICE_TYPE_TBD)) {
\r
466 resetSearchAndRecordCommands();
\r
467 pzresp.resetAllSessionData();
\r
469 serviceType = type;
\r
470 if (serviceType.equals(SERVICE_TYPE_PZ2)) {
\r
471 searchClient = pz2Client;
\r
472 logger.info("Setting a Pazpar2 client to serve requests.");
\r
473 } else if (serviceType.equals(SERVICE_TYPE_SP)) {
\r
474 searchClient = spClient;
\r
475 logger.info("Setting a Service Proxy client to serve requests.");
\r
477 logger.info("Clearing search client. No client defined to serve requests at this point.");
\r
478 searchClient = null;
\r