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