eaff6929672f712c09465e9a5625e0d11874f375
[mkjsf-moved-to-github.git] / src / main / java / com / indexdata / mkjsf / pazpar2 / commands / CommandParameter.java
1 package com.indexdata.mkjsf.pazpar2.commands;\r
2 \r
3 import java.io.Serializable;\r
4 import java.io.UnsupportedEncodingException;\r
5 import java.net.URLEncoder;\r
6 import java.util.ArrayList;\r
7 import java.util.Arrays;\r
8 import java.util.Iterator;\r
9 import java.util.List;\r
10 \r
11 import org.apache.log4j.Logger;\r
12 \r
13 /**\r
14  * Represents a Pazpar2 command parameter with a name, an operator, \r
15  * a simple value and/or one or more complex values (expressions).\r
16  * <p>Examples</p>\r
17  * <ul>\r
18  *  <li>{name}{=}{value}</li>\r
19  *  <li>{name}{=}{value} AND {expr1=value1} AND {expr2=value2}</li>\r
20  *  <li>{name}{=}{expr1~value1},{expr2~value2}</li> \r
21  * </ul> \r
22  * @author Niels Erik\r
23  *\r
24  */\r
25 public class CommandParameter implements Serializable {\r
26 \r
27   private static Logger logger = Logger.getLogger(CommandParameter.class);\r
28   \r
29   private static final long serialVersionUID = 625502285668766749L;  \r
30   String name = null;\r
31   String operator = null;\r
32   String value = null;\r
33   List<Expression> expressions = new ArrayList<Expression>();\r
34   private static List<String> nologparams = Arrays.asList("password");\r
35   \r
36   public CommandParameter (String name) {\r
37     logger.trace("Instantiating command parameter '" + name + "'");\r
38     this.name = name;\r
39   }\r
40   \r
41   /**\r
42    * Instantiates a parameter with a simple value and one or more expressions\r
43    * \r
44    * @param name\r
45    * @param operator\r
46    * @param value\r
47    * @param expressions\r
48    */\r
49   public CommandParameter (String name, String operator, String value, Expression... expressions) {\r
50     logger.trace("Instantiating command parameter " + name + " with value [" + value + "] and expressions: [" + expressions + "]");\r
51     this.name = name;\r
52     this.operator = operator;\r
53     this.value = value;\r
54     for (Expression expr : expressions) {\r
55       this.expressions.add(expr);\r
56     }\r
57   }\r
58   \r
59   /**\r
60    * Instantiates a parameter with one or more expressions\r
61    * @param name\r
62    * @param operator\r
63    * @param expressions\r
64    */\r
65   public CommandParameter (String name, String operator, Expression... expressions) {\r
66     logger.trace("Instantiating command parameter " + name + " with expressions: [" + expressions + "]");\r
67     this.name = name;\r
68     this.operator = operator;    \r
69     for (Expression expr : expressions) {\r
70       this.expressions.add(expr);\r
71     }\r
72   }\r
73 \r
74 \r
75   /**\r
76    * Instantiates a parameter with a simple value\r
77    * @param name\r
78    * @param operator\r
79    * @param value\r
80    */\r
81   public CommandParameter (String name, String operator, String value) {\r
82     if (!nologparams.contains(name)) logger.trace("Instantiating command parameter '" + name + "' with String: [" + value + "]");    \r
83     this.name = name;\r
84     this.operator = operator;\r
85     this.value = value;    \r
86   }\r
87   \r
88   /**\r
89    * Instantiates a parameter with a numeric value\r
90    * @param name\r
91    * @param operator\r
92    * @param value\r
93    */\r
94   public CommandParameter (String name, String operator, int value) {\r
95     logger.trace("Instantiating command parameter '" + name + "' with int: [" + value + "]");\r
96     this.name = name;\r
97     this.operator = operator;\r
98     this.value = value+"";    \r
99   }\r
100 \r
101   /**\r
102    * Returns the name (left of operator) of this parameter\r
103    * \r
104    * @return name (left of operator) of this parameter\r
105    */\r
106   public String getName () {\r
107     return name;\r
108   }\r
109   \r
110   /**\r
111    * Returns a list of all current expressions\r
112    * \r
113    * @return a list of all current expressions\r
114    */\r
115   public List<Expression> getExpressions () {\r
116     return expressions;\r
117   }\r
118 \r
119   /**\r
120    * Returns expressions selected by their left-hand keys - as in 'expressionField=value'.\r
121    * <p>\r
122    * If the parameter has expressions expr1=x,expr2=y,expr3=z,expr1=u then invoking this method \r
123    * with {"expr1","expr3"} would return expr1=x,expr3=z,expr1=u but not expr2=y.   \r
124    * </p>\r
125    * @param expressionFields The expression types to return\r
126    * @return a list of expressions with the given keys to the left of the operator\r
127    * \r
128    */\r
129   public List<Expression> getExpressions(String... expressionFields) {\r
130     List<String> requestedFields = Arrays.asList(expressionFields);\r
131     List<Expression> exprs = new ArrayList<Expression>();\r
132     for (Expression expr : expressions) {\r
133       if (requestedFields.contains(expr.getField())) {\r
134         exprs.add(expr);\r
135       }\r
136     }\r
137     return exprs;\r
138   }\r
139   \r
140   /**\r
141    * Adds an expression to the end of the list of current expressions (if any)\r
142    * \r
143    * @param expression to add\r
144    */\r
145   public void addExpression(Expression expression) {\r
146     logger.debug("Adding expression [" + expression + "] to '" + name + "'");\r
147     this.expressions.add(expression);\r
148   }\r
149   \r
150   /**\r
151    * Removes a single expression identified by all its characteristics\r
152    * \r
153    * @param expression to remove\r
154    */\r
155   public void removeExpression(Expression expression) {\r
156     for (Expression expr : expressions) {\r
157       if (expr.toString().equals(expression.toString())) {\r
158         expressions.remove(expr);\r
159         break;\r
160       }\r
161     }    \r
162   }\r
163   \r
164   /**\r
165    * Removes all expressions that appear after the provided expression and that \r
166    * have the given keys to the left of their operators - as in 'expressionField=value'.\r
167    * <p>\r
168    * This method is intended for bread crumb-like UI controls\r
169    * </p>\r
170    * @param expression The expression to use a starting point for removal (not inclusive)\r
171    * @param expressionFields The expression fields to remove\r
172    */\r
173   public void removeExpressionsAfter (Expression expression, String... expressionFields) {\r
174     List<String> exprFieldsToRemove = Arrays.asList(expressionFields);\r
175     int fromIdx = 0;    \r
176     for (Expression expr : expressions) {      \r
177       fromIdx++;\r
178       if (expr.toString().equals(expression.toString())) {        \r
179         break;\r
180       }      \r
181     }\r
182     if (fromIdx<expressions.size()) {      \r
183       Iterator<Expression> candidatesForRemoval = expressions.subList(fromIdx, expressions.size()).iterator();\r
184       while (candidatesForRemoval.hasNext()) {\r
185         Expression exp = candidatesForRemoval.next();\r
186         if (exprFieldsToRemove.contains(exp.getField())) {\r
187           expressions.remove(exp);\r
188         }\r
189       }\r
190     }\r
191   }\r
192   \r
193   /**\r
194    * Removes expressions selected by their left-of-operator fields/keys - as in 'expressionField=value'.\r
195    * <p>\r
196    * If the parameter has expressions expr1=x,expr2=y,expr3=z,expr1=u then invoking this method \r
197    * with {"expr1","expr3"} would remove expr1=x,expr3=z and expr1=u but leave expr2=y.   \r
198    * </p>\r
199    * @param expressionFields The expression types (by field) to remove\r
200    * @return a list of expressions with the given left-of-operator keys\r
201    * \r
202    */\r
203   public void removeExpressions (String... expressionFields) {\r
204     List<String> fieldsToRemove = Arrays.asList(expressionFields);\r
205     Iterator<Expression> i = expressions.iterator();\r
206     while (i.hasNext()) {\r
207        Expression expr = i.next(); \r
208        if (fieldsToRemove.contains(expr.getField())) {\r
209          logger.trace("Removing expression: " + expr.toString());\r
210          i.remove();\r
211        }\r
212     }\r
213   }\r
214 \r
215   /**\r
216    *   \r
217    * @return true if an operator was defined for this parameter yet\r
218    */\r
219   public boolean hasOperator() {\r
220     return operator != null;\r
221   }\r
222   \r
223   /**\r
224    * Returns true if this parameter has a simple value\r
225    * \r
226    * @return true if this parameter has a simple value\r
227    */\r
228   public boolean hasValue() {\r
229     return value != null && value.length()>0;\r
230   }\r
231   \r
232   /**\r
233    * Returns true if this parameter has expressions (complex values)\r
234    * \r
235    * @return true if this parameter has expressions (complex values)\r
236    */\r
237   public boolean hasExpressions() {\r
238     return expressions.size()>0;\r
239   }\r
240   \r
241   /**\r
242    * Returns true if this parameter has expressions of the given type,\r
243    * that is, expressions where the left-of-operator key equals 'expressionField'\r
244    * \r
245    * @param expressionField the type of expression to look for\r
246    * @return true if this parameter has expressions of the given type,\r
247    *  that is, expressions where the left-of-operator key equals 'expressionField'\r
248    */\r
249   public boolean hasExpressions(String expressionField) {    \r
250     for (Expression expr : expressions) {\r
251       if (expr.getField().equals(expressionField)) {\r
252         return true;\r
253       }\r
254     }     \r
255     return false;    \r
256   }\r
257   \r
258   /**\r
259    * Returns a URL encoded string of this parameter with name, operator, simple value and/or expressions\r
260    * \r
261    * @return URL encoded string of this parameter with name, operator, simple value and/or expressions\r
262    */\r
263   public String getEncodedQueryString () {\r
264     try {\r
265       return name + operator + URLEncoder.encode(getValueWithExpressions(),"UTF-8");\r
266     } catch (UnsupportedEncodingException e) {\r
267       e.printStackTrace();\r
268       return null;\r
269     }\r
270   }\r
271     \r
272   /**\r
273    * Returns the simple parameter value or null if no simple value was set for this parameter\r
274    * \r
275    * @return the simple parameter value, null if no simple value was set for this parameter \r
276    */\r
277   public String getSimpleValue() {    \r
278     return value; \r
279   }\r
280   \r
281   /**\r
282    * Returns the simple parameter value and/or any expressions, separated by 'AND'\r
283    * \r
284    * @return the simple parameter value and/or any expressions separated by 'AND'\r
285    */\r
286   public String getValueWithExpressions () {\r
287     StringBuilder completeValue = new StringBuilder((value==null ? "" : value));\r
288     boolean first=true;\r
289     for (Expression expr : expressions) {      \r
290       if (value == null && first) {\r
291         first = false;\r
292         completeValue.append(expr.toString());\r
293       } else {\r
294         completeValue.append(" AND " + expr.toString());\r
295       }\r
296     }\r
297     return completeValue.toString();    \r
298   }  \r
299   \r
300   @Override\r
301   public boolean equals (Object otherParameter) {\r
302     return\r
303         ((otherParameter instanceof CommandParameter)\r
304          && this.getValueWithExpressions().equals(((CommandParameter) otherParameter).getValueWithExpressions()));\r
305   }\r
306   \r
307   @Override\r
308   public int hashCode () {\r
309     return getValueWithExpressions().hashCode();\r
310   }\r
311   \r
312   public String toString() {\r
313     return getValueWithExpressions();\r
314   }\r
315   \r
316   /**\r
317    * Clones the CommandParameter\r
318    * \r
319    * @return a deep, detached clone of this command parameter, for copying \r
320    * a parameter to a new state.  \r
321    */\r
322   public CommandParameter copy() {\r
323     logger.trace("Copying parameter '"+ name + "' for modification");\r
324     CommandParameter newParam = new CommandParameter(name);\r
325     newParam.value = this.value;\r
326     newParam.operator = this.operator;\r
327     for (Expression expr : expressions) {\r
328       newParam.addExpression(expr.copy());      \r
329     }\r
330     return newParam;\r
331   }\r
332   \r
333 }\r