f9f76a22e70375558765f5d03fe5a60fef1586ec
[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 compoundExpression) {\r
74     if (compoundExpression != null && compoundExpression.length()>0) {\r
75       // Split expression by commas that are not escaped (with backslash)\r
76       String[] subExpressions = compoundExpression.split("(?<!\\\\),");\r
77       for (int i=0; i<subExpressions.length; i++) {\r
78         if (subExpressions[i].split("[=~]").length==1) {\r
79           removeFilters(subExpressions[i].split("[=~]")[0]);\r
80         } else if (subExpressions[i].split("[=~]").length==2) {\r
81           if (getParameter("filter") == null) {\r
82             setParameter(new FilterParameter(new Expression(subExpressions[i])));\r
83           } else {\r
84             if (getParameter("filter").hasExpressions(subExpressions[i].split("[=~]")[0])) {\r
85               getParameter("filter").removeExpressions(subExpressions[i].split("[=~]")[0]);\r
86             }\r
87             getParameter("filter").addExpression(new Expression(subExpressions[i]));\r
88           }\r
89         } else {\r
90           logger.error("Could not parse filter expression [" + subExpressions[i] + "]");\r
91         }\r
92       }\r
93     }\r
94   }\r
95   \r
96   /**\r
97    * Sets the <code>filter</code> parameter. See Pazpar2 documentation for details.\r
98    */  \r
99   public void setFilter(String field, String operator, String value, String label) {\r
100     setParameter(new FilterParameter(new Expression(field,operator,value,label)));\r
101   }\r
102 \r
103   /**\r
104    * Checks if there are any filter expressions matching any of the given expressionFields\r
105    * @param expressionFields expression fields (left-of-operator entities) to look for\r
106    * @return true if expression(s) found with any of <code>expressionFields</code> \r
107    */\r
108   public boolean hasFilterExpression(String... expressionFields) {\r
109     logger.trace("Checking for filter expression for " + Arrays.deepToString(expressionFields));\r
110     for (String field : expressionFields) {\r
111       if (getFilterExpressions(field) != null && getFilterExpressions(field).size()>0) {\r
112         logger.trace("Filter expression found (" + field + ")");\r
113         return true;\r
114       }  \r
115     }\r
116     logger.trace("No filter expressions found");\r
117     return false;\r
118   }\r
119 \r
120   \r
121   /** \r
122    * Returns the <code>filter</code> parameter value.\r
123    */\r
124   public String getFilter() {\r
125     return getParameter("filter") == null ? null : ((FilterParameter)getParameter("filter")).getValueWithExpressions();\r
126   }\r
127   \r
128   /**\r
129    * Returns the first filter expression of the given type\r
130    * @param expressionField expression field (left-of-operator entity) to look for\r
131    * @return the first filter expression found with the field <code>expressionField</code> or null if none found \r
132    */\r
133   public Expression getOneFilterExpression(String expressionField) {\r
134     List<Expression> exprs = getFilterExpressions(expressionField);\r
135     if (exprs != null && exprs.size()>0) {\r
136       if (exprs.size()>1) {\r
137         logger.warn("More that one filter expression found for [" + expressionField + "] but only asked to return the first one");\r
138       }\r
139       return exprs.get(0);\r
140     } else {\r
141       return null;\r
142     }    \r
143   }\r
144 \r
145   \r
146   /**\r
147    * Returns list of all filter expressions \r
148    */\r
149   public List<Expression> getFilterExpressions() {\r
150     return getParameter("filter").getExpressions();\r
151   }\r
152     \r
153   \r
154   public List<Expression> getFilterExpressions(String... expressionFields) {\r
155     logger.trace("Checking for filter parameter");\r
156     if (parameters.get("filter")!=null) {\r
157       logger.trace("Found");\r
158       return getParameter("filter").getExpressions(expressionFields);\r
159     } else {\r
160       logger.trace("Not found");\r
161       return null;\r
162     }\r
163   }\r
164   \r
165   public boolean hasFilter () {\r
166     return getFilter().length()>0;\r
167   }\r
168 \r
169   /**\r
170    * Adds a filter expression with a label for display. The filter is added to the end\r
171    * of an ordered list.  \r
172    * \r
173    * @param field\r
174    * @param operator\r
175    * @param value\r
176    * @param label\r
177    */\r
178   public void addFilter(String field, String operator, String value, String label) {\r
179     if (getParameter("filter") == null) {\r
180       setFilter(field + operator + value);\r
181     } else {\r
182       addExpression("filter",new Expression(field,operator,value,(label != null ? label : value)));\r
183     }\r
184   }\r
185 \r
186   /**\r
187    * Clears the filter parameter\r
188    */\r
189   public void removeFilters () {\r
190     removeParameter("filter");\r
191   }\r
192 \r
193   /**\r
194    * Removes a filter expression by exact attributes\r
195    * \r
196    * @param field\r
197    * @param operator\r
198    * @param value\r
199    */\r
200   public void removeFilter(String field, String operator, String value) {\r
201     removeExpression("filter",new Expression(field, operator, value, null));\r
202   }\r
203   \r
204   /**\r
205    * Removes all filter expressions matching a field listed in <code>fieldsToRemove</code>\r
206    * @param fieldsToRemove\r
207    */\r
208   public void removeFilters(String... fieldsToRemove) {    \r
209     removeExpressions("filter",fieldsToRemove);    \r
210   }  \r
211 \r
212   /**\r
213    * Removes filter expressions coming after the expression matching the provided filter expression, \r
214    * if they have a field listed in <code>fieldsToRemove</code>. To be used for bread crumb like UI \r
215    * controls.\r
216    * \r
217    * @param field\r
218    * @param operator\r
219    * @param value\r
220    * @param fieldsToRemove\r
221    */\r
222   public void removeFiltersAfter(String field, String operator, String value, String... fieldsToRemove) {     \r
223     removeExpressionsAfter("filter",new Expression(field,operator,value,null),fieldsToRemove);    \r
224   }\r
225 \r
226   /**\r
227    * Sets the <code>limit</code> parameter. See Pazpar2 documentation for details.\r
228    */  \r
229   public void setLimit (String compoundExpression) {   \r
230     if (compoundExpression != null && compoundExpression.length()>0) {\r
231       // Split expression by commas that are not escaped (with backslash)\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