dcbb3232c13bb919c011bd48e90f222de712dab6
[mkjsf-moved-to-github.git] / src / main / java / com / indexdata / mkjsf / pazpar2 / commands / SearchCommand.java
1 package com.indexdata.mkjsf.pazpar2.commands;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Arrays;\r
5 import java.util.List;\r
6 import java.util.StringTokenizer;\r
7 \r
8 import javax.enterprise.context.SessionScoped;\r
9 import javax.inject.Named;\r
10 \r
11 import org.apache.log4j.Logger;\r
12 \r
13 import com.indexdata.mkjsf.pazpar2.Pz2Service;\r
14 import com.indexdata.mkjsf.pazpar2.commands.sp.SearchCommandSp;\r
15 import com.indexdata.mkjsf.pazpar2.commands.sp.ServiceProxyCommand;\r
16 import com.indexdata.mkjsf.pazpar2.data.ResponseDataObject;\r
17 \r
18 /**\r
19  * <b><code>search</code></b> Pazpar2 command, referenced as: <code>pzreq.search</code> \r
20  * \r
21  * @author Niels Erik\r
22  *\r
23  */\r
24 @SessionScoped @Named\r
25 public class SearchCommand extends Pazpar2Command implements ServiceProxyCommand {\r
26   \r
27   private static final long serialVersionUID = -1888520867838597236L;\r
28   private static Logger logger = Logger.getLogger(SearchCommand.class);  \r
29     \r
30   public SearchCommand() {\r
31     super("search");\r
32   }\r
33   \r
34   public ResponseDataObject run() {\r
35     logger.info("Running " + getCommandName());\r
36     Pz2Service.get().getStateMgr().hasPendingStateChange("search",false);\r
37     Pz2Service.get().getPzresp().resetSearchAndBeyond();\r
38     Pz2Service.get().getPzreq().getRecord().removeParametersInState();        \r
39     Pz2Service.get().getPzreq().getShow().setParameterInState(new CommandParameter("start","=",0));    \r
40     Pz2Service.get().getSearchClient().setSearchCommand(this);\r
41     return super.run();\r
42   }\r
43 \r
44   /**\r
45    * Sets the <code>query</code> parameter. See Pazpar2 documentation for details.\r
46    */  \r
47   public void setQuery(String query) {    \r
48     setParameter(new QueryParameter("query","=",query));\r
49   }\r
50   \r
51   public void setBooleanOperatorForQuery(String operator) {\r
52     Pazpar2Command copy = this.copy();\r
53     ((QueryParameter) getParameter("query")).setBooleanOperator(operator);\r
54     checkInState(copy);\r
55   }\r
56   \r
57   /** \r
58    * Returns the simple part of the <code>query</code> parameter value, excluding parts that \r
59    * were added as expressions (that is, not set with <code>setQuery()</code>).\r
60    */\r
61   public String getQuery () {    \r
62     return getParameter("query") == null ? null  : ((QueryParameter)getParameter("query")).getSimpleValue();\r
63   }\r
64 \r
65   /** \r
66    * Returns the complete <code>query</code> parameter value, including expressions.\r
67    */\r
68   public String getExtendedQuery () {    \r
69     return getParameter("query") == null ? null  : ((QueryParameter)getParameter("query")).getValueWithExpressions();\r
70   }\r
71     \r
72   /**\r
73    * Sets the <code>filter</code> parameter. See Pazpar2 documentation for details.\r
74    */  \r
75   public void setFilter(String compoundExpression) {\r
76     if (compoundExpression != null && compoundExpression.length()>0) {\r
77       String[] subExpressions = compoundExpression.split(",");\r
78       for (int i=0; i<subExpressions.length; i++) {\r
79         if (subExpressions[i].split("[=~]").length==1) {\r
80           removeFilters(subExpressions[i].split("[=~]")[0]);\r
81         } else if (subExpressions[i].split("[=~]").length==2) {\r
82           if (getParameter("filter") == null) {\r
83             setParameter(new FilterParameter(new Expression(subExpressions[i])));\r
84           } else {\r
85             if (getParameter("filter").hasExpressions(subExpressions[i].split("[=~]")[0])) {\r
86               getParameter("filter").removeExpressions(subExpressions[i].split("[=~]")[0]);\r
87             }\r
88             getParameter("filter").addExpression(new Expression(subExpressions[i]));\r
89           }\r
90         } else {\r
91           logger.error("Could not parse filter expression [" + subExpressions[i] + "]");\r
92         }\r
93       }\r
94     }\r
95   }\r
96   \r
97   /**\r
98    * Sets the <code>filter</code> parameter. See Pazpar2 documentation for details.\r
99    */  \r
100   public void setFilter(String field, String operator, String value, String label) {\r
101     setParameter(new FilterParameter(new Expression(field,operator,value,label)));\r
102   }\r
103 \r
104   /**\r
105    * Checks if there are any filter expressions matching any of the given expressionFields\r
106    * @param expressionFields expression fields (left-of-operator entities) to look for\r
107    * @return true if expression(s) found with any of <code>expressionFields</code> \r
108    */\r
109   public boolean hasFilterExpression(String... expressionFields) {\r
110     logger.trace("Checking for filter expression for " + Arrays.deepToString(expressionFields));\r
111     for (String field : expressionFields) {\r
112       if (getFilterExpressions(field) != null && getFilterExpressions(field).size()>0) {\r
113         logger.trace("Filter expression found (" + field + ")");\r
114         return true;\r
115       }  \r
116     }\r
117     logger.trace("No filter expressions found");\r
118     return false;\r
119   }\r
120 \r
121   \r
122   /** \r
123    * Returns the <code>filter</code> parameter value.\r
124    */\r
125   public String getFilter() {\r
126     return getParameter("filter") == null ? null : ((FilterParameter)getParameter("filter")).getValueWithExpressions();\r
127   }\r
128   \r
129   /**\r
130    * Returns the first filter expression of the given type\r
131    * @param expressionField expression field (left-of-operator entity) to look for\r
132    * @return the first filter expression found with the field <code>expressionField</code> or null if none found \r
133    */\r
134   public Expression getOneFilterExpression(String expressionField) {\r
135     List<Expression> exprs = getFilterExpressions(expressionField);\r
136     if (exprs != null && exprs.size()>0) {\r
137       if (exprs.size()>1) {\r
138         logger.warn("More that one filter expression found for [" + expressionField + "] but only asked to return the first one");\r
139       }\r
140       return exprs.get(0);\r
141     } else {\r
142       return null;\r
143     }    \r
144   }\r
145 \r
146   \r
147   /**\r
148    * Returns list of all filter expressions \r
149    */\r
150   public List<Expression> getFilterExpressions() {\r
151     return getParameter("filter").getExpressions();\r
152   }\r
153     \r
154   \r
155   public List<Expression> getFilterExpressions(String... expressionFields) {\r
156     logger.trace("Checking for filter parameter");\r
157     if (parameters.get("filter")!=null) {\r
158       logger.trace("Found");\r
159       return getParameter("filter").getExpressions(expressionFields);\r
160     } else {\r
161       logger.trace("Not found");\r
162       return null;\r
163     }\r
164   }\r
165   \r
166   public boolean hasFilter () {\r
167     return getFilter().length()>0;\r
168   }\r
169 \r
170   /**\r
171    * Adds a filter expression with a label for display. The filter is added to the end\r
172    * of an ordered list.  \r
173    * \r
174    * @param field\r
175    * @param operator\r
176    * @param value\r
177    * @param label\r
178    */\r
179   public void addFilter(String field, String operator, String value, String label) {\r
180     if (getParameter("filter") == null) {\r
181       setFilter(field + operator + value);\r
182     } else {\r
183       addExpression("filter",new Expression(field,operator,value,(label != null ? label : value)));\r
184     }\r
185   }\r
186 \r
187   /**\r
188    * Clears the filter parameter\r
189    */\r
190   public void removeFilters () {\r
191     removeParameter("filter");\r
192   }\r
193 \r
194   /**\r
195    * Removes a filter expression by exact attributes\r
196    * \r
197    * @param field\r
198    * @param operator\r
199    * @param value\r
200    */\r
201   public void removeFilter(String field, String operator, String value) {\r
202     removeExpression("filter",new Expression(field, operator, value, null));\r
203   }\r
204   \r
205   /**\r
206    * Removes all filter expressions matching a field listed in <code>fieldsToRemove</code>\r
207    * @param fieldsToRemove\r
208    */\r
209   public void removeFilters(String... fieldsToRemove) {    \r
210     removeExpressions("filter",fieldsToRemove);    \r
211   }  \r
212 \r
213   /**\r
214    * Removes filter expressions coming after the expression matching the provided filter expression, \r
215    * if they have a field listed in <code>fieldsToRemove</code>. To be used for bread crumb like UI \r
216    * controls.\r
217    * \r
218    * @param field\r
219    * @param operator\r
220    * @param value\r
221    * @param fieldsToRemove\r
222    */\r
223   public void removeFiltersAfter(String field, String operator, String value, String... fieldsToRemove) {     \r
224     removeExpressionsAfter("filter",new Expression(field,operator,value,null),fieldsToRemove);    \r
225   }\r
226 \r
227   /**\r
228    * Sets the <code>limit</code> parameter. See Pazpar2 documentation for details.\r
229    */  \r
230   public void setLimit (String compoundExpression) {   \r
231     if (compoundExpression != null && compoundExpression.length()>0) {\r
232       String[] subExpressions = compoundExpression.split(",");\r
233       for (int i=0; i<subExpressions.length; i++) {\r
234         if (subExpressions[i].split("[=~]").length==1) {\r
235           removeLimits(subExpressions[i].split("[=~]")[0]);\r
236         } else if (subExpressions[i].split("[=~]").length==2) {\r
237           if (getParameter("limit") == null) {\r
238             setParameter(new LimitParameter(new Expression(subExpressions[i])));\r
239           } else {\r
240             if (getParameter("limit").hasExpressions(subExpressions[i].split("[=~]")[0])) {\r
241               getParameter("limit").removeExpressions(subExpressions[i].split("[=~]")[0]);\r
242             }\r
243             getParameter("limit").addExpression(new Expression(subExpressions[i]));\r
244           }\r
245         } else {\r
246           logger.error("Could not parse limit expression [" + subExpressions[i] + "]");\r
247         }\r
248       }\r
249     }\r
250   }\r
251   \r
252   /**\r
253    * Sets the <code>limit</code> parameter including a label. See Pazpar2 documentation for details.\r
254    */  \r
255   public void setLimit(String field, String operator, String value, String label) {\r
256     setParameter(new LimitParameter(new Expression(field,operator,value,label)));\r
257   }\r
258       \r
259   /** \r
260    * Returns the <code>limit</code> parameter value.\r
261    */\r
262   public String getLimit () {\r
263     return getParameter("limit") == null ? null : ((LimitParameter)getParameter("limit")).getValueWithExpressions();    \r
264   }\r
265     \r
266   /**\r
267    * Checks if there are any limit expressions matching any of the given expressionFields\r
268    * @param expressionFields expression fields (left-of-operator entities) to look for\r
269    * @return true if expression(s) found with any of <code>expressionFields</code> \r
270    */\r
271   public boolean hasLimitExpression(String... expressionFields) {\r
272     logger.trace("Checking for limit expression for " + Arrays.deepToString(expressionFields));\r
273     for (String field : expressionFields) {\r
274       if (getLimitExpressions(field) != null && getLimitExpressions(field).size()>0) {\r
275         logger.trace("Limit expression found (" + field + ")");\r
276         return true;\r
277       }  \r
278     }\r
279     logger.trace("No limit expressions found");\r
280     return false;\r
281   }\r
282   \r
283   /**\r
284    * Returns the first limit expression of the given type\r
285    * @param expressionField expression field (left-of-operator entity) to look for\r
286    * @return the first limit expression found with the field <code>expressionField</code> or null if none found \r
287    */\r
288   public Expression getOneLimitExpression(String expressionField) {\r
289     List<Expression> exprs = getLimitExpressions(expressionField);\r
290     if (exprs != null && exprs.size()>0) {\r
291       if (exprs.size()>1) {\r
292         logger.warn("More that one limit expression found for [" + expressionField + "] but only asked to return the first one");\r
293       }\r
294       return exprs.get(0);\r
295     } else {\r
296       return null;\r
297     }    \r
298   }\r
299   \r
300   /**\r
301    * Return a list of all current limit expressions\r
302    */\r
303   public List<Expression> getLimitExpressions() {\r
304     return getParameter("limit").getExpressions();\r
305   }\r
306   \r
307   /**\r
308    * Returns a list of limit expressions with fields that matches one of <code>expressionFields</code>\r
309    * \r
310    * @param expressionFields limit expressions to look for\r
311    */\r
312   public List<Expression> getLimitExpressions(String... expressionFields) {\r
313     logger.trace("Checking for limit parameter");\r
314     if (parameters.get("limit")!=null) {\r
315       logger.trace("Found");\r
316       return getParameter("limit").getExpressions(expressionFields);\r
317     } else {\r
318       logger.trace("Not found");\r
319       return null;\r
320     }\r
321   }\r
322   \r
323   /**\r
324    * Adds a limit expression with a label for display. The limit is added to the end\r
325    * of an ordered list.  \r
326    * \r
327    * @param field\r
328    * @param operator\r
329    * @param value\r
330    * @param label\r
331    */\r
332   public void addLimit(String field, String operator, String value, String label) {\r
333     if (getParameter("limit") == null) {\r
334       setLimit(field, operator, value, label);\r
335     } else {\r
336       addExpression("limit",new Expression(field,operator,value,label));      \r
337     }\r
338   }\r
339   \r
340   /**\r
341    * Clears the limit parameter\r
342    */\r
343   public void removeLimits() {\r
344     removeParameter("limit");\r
345   }\r
346   \r
347   /**\r
348    * Removes all limit expressions that have fields as listed in <code>fieldsToRemove</code>\r
349    * @param fieldsToRemove\r
350    */\r
351   public void removeLimits(String... fieldsToRemove) {    \r
352     removeExpressions("limit",fieldsToRemove);    \r
353   }\r
354   \r
355   /**\r
356    * Removes a limit expression by exact attributes\r
357    * \r
358    * @param field\r
359    * @param operator\r
360    * @param value\r
361    */\r
362   public void removeLimit(String field, String operator, String value) {\r
363     removeExpression("limit",new Expression(field, operator, value, null));    \r
364   }\r
365   \r
366   /**\r
367    * Removes limit expressions coming after the provided limit expression, if they have a field listed in\r
368    * <code>fieldsToRemove</code>. To be used for bread crumb like UI controls.\r
369    * \r
370    * @param field\r
371    * @param operator\r
372    * @param value\r
373    * @param fieldsToRemove\r
374    */\r
375   public void removeLimitsAfter(String field, String operator, String value, String... fieldsToRemove) {     \r
376     removeExpressionsAfter("limit",new Expression(field,operator,value,null),fieldsToRemove);    \r
377   }\r
378 \r
379         \r
380   /**\r
381    * Sets the <code>startrecs</code> parameter. See Pazpar2 documentation for details.\r
382    */  \r
383   public void setStartrecs (String startrecs) {\r
384     setParameter(new CommandParameter("startrecs","=",startrecs));\r
385   }\r
386   \r
387   /** \r
388    * Returns the <code>startrecs</code> parameter value.\r
389    */\r
390   public String getStartrecs () {\r
391     return getParameterValue("startrecs");\r
392   }\r
393   \r
394   /**\r
395    * Sets the <code>maxrecs</code> parameter. See Pazpar2 documentation for details.\r
396    */  \r
397   public void setMaxrecs (String maxrecs) {\r
398     setParameter(new CommandParameter("maxrecs","=",maxrecs));\r
399   }\r
400   \r
401   /** \r
402    * Returns the <code>maxrecs</code> parameter value.\r
403    */\r
404   public String getMaxrecs () {\r
405     return getParameterValue("maxrecs");\r
406   }\r
407   \r
408   /**\r
409    * Sets the <code>sort</code> parameter. See Pazpar2 documentation for details.\r
410    */  \r
411   public void setSort (String sort) {\r
412     setParameter(new CommandParameter("sort","=",sort));\r
413   }\r
414   \r
415   /** \r
416    * Returns the <code>sort</code> parameter value.\r
417    */\r
418   public String getSort () {\r
419     return getParameterValue("sort");\r
420   }\r
421   \r
422   /**\r
423    * Sets the <code>rank</code> parameter. See Pazpar2 documentation for details.\r
424    */  \r
425   public void setRank (String rank) {\r
426     setParameter(new CommandParameter("rank","=",rank));\r
427   }\r
428   \r
429   /** \r
430    * Returns the <code>rank</code> parameter value.\r
431    */\r
432   public String getRank () {\r
433     return getParameterValue("rank");\r
434   }\r
435   \r
436   /**\r
437    * Sets the <code>mergekey</code> parameter. See Pazpar2 documentation for details.\r
438    */  \r
439   public void setMergekey (String mergekey) {\r
440     setParameter(new CommandParameter("mergekey","=",mergekey));\r
441   }\r
442   \r
443   /** \r
444    * Returns the <code>mergekey</code> parameter value.\r
445    */\r
446   public String getMergekey () {\r
447     return getParameterValue("mergekey");\r
448   }\r
449   \r
450   \r
451   /**\r
452    * Adds an expression - for instance a facet criterion, with an optional label - to the query parameter\r
453    * \r
454    * <p>Example:</p>\r
455    * <ul>\r
456    *  <li><code>{au}{=}{"Steinbeck, John"}{Steinbeck, John}</code>\r
457    * </ul>\r
458    */\r
459   public void addQueryExpression(String field, String operator, String term, String label) {\r
460     if (term != null && term.length()>0) { \r
461       addExpression("query", new Expression(field,operator,term,label));                  \r
462     }            \r
463   }\r
464   \r
465   /**\r
466    * Removes a query expression - for instance a facet criterion - by its exact attributes\r
467    * \r
468    * @param field\r
469    * @param operator\r
470    * @param value\r
471    */\r
472   public void removeQueryExpression(String field, String operator, String value) {\r
473     removeExpression("query",new Expression(field, operator, value, null));    \r
474   }\r
475 \r
476   \r
477   /**\r
478    * Sets a facet to limit the current query by. The \r
479    * facet is appended to the query string itself (rather\r
480    * as a separately managed entity. It will thus appear\r
481    * in a query field as retrieved by getQuery(). It will\r
482    * not be removed by removeFacet(...)\r
483    * \r
484    * @param facetKey  i.e. 'au' for author\r
485    * @param term i.e. 'Dickens, Charles'\r
486    */\r
487   public void setFacetOnQuery (String facetKey, String term) {\r
488     String facetExpression = facetKey + "=" + term;    \r
489     if (term != null && term.length()>0) {\r
490       String currentQuery= getQuery();\r
491       setParameter(new QueryParameter("query","=", currentQuery + " and " + facetExpression));      \r
492     }            \r
493   }\r
494       \r
495   /**\r
496    * Removes a facet set by setFacet(...)\r
497    * \r
498    * Will not remove facets set by setFacetOnQuery(...)\r
499    *  \r
500    * @param facetKey i.e. 'au' for author\r
501    * @param term i.e. 'Dickens, Charles'\r
502    */\r
503   public void removeFacet(String facetKey, String term) {\r
504     if (getParameter("query") != null) {\r
505       removeExpression("query",new Expression(facetKey,"=",term,null));\r
506     }\r
507   }\r
508       \r
509   public SearchCommand copy () {\r
510     SearchCommand newCommand = new SearchCommand();\r
511     for (String parameterName : parameters.keySet()) {\r
512       newCommand.setParameterInState(parameters.get(parameterName).copy());      \r
513     }\r
514     return newCommand;\r
515   }\r
516 \r
517   @Override\r
518   public ServiceProxyCommand getSp() {\r
519     return new SearchCommandSp(this);\r
520   }\r
521 \r
522   @Override\r
523   public boolean spOnly() {\r
524     return false;\r
525   }\r
526 \r
527 }\r