1 package com.indexdata.mkjsf.pazpar2.commands;
\r
3 import java.io.Serializable;
\r
4 import java.util.HashMap;
\r
5 import java.util.Map;
\r
6 import java.util.StringTokenizer;
\r
8 import org.apache.log4j.Logger;
\r
10 import com.indexdata.mkjsf.pazpar2.ClientCommandResponse;
\r
11 import com.indexdata.mkjsf.pazpar2.HttpResponseWrapper;
\r
12 import com.indexdata.mkjsf.pazpar2.Pz2Service;
\r
13 import com.indexdata.mkjsf.pazpar2.SearchClient;
\r
14 import com.indexdata.mkjsf.pazpar2.commands.sp.ServiceProxyCommand;
\r
15 import com.indexdata.mkjsf.pazpar2.data.ResponseDataObject;
\r
16 import com.indexdata.mkjsf.pazpar2.data.ResponseParser;
\r
17 import com.indexdata.mkjsf.pazpar2.data.Responses;
\r
20 * Represents a generic Pazpar2 or Service Proxy command with all its current parameters, and has
\r
21 * methods for executing the command against the currently selected Pazpar2 service</p>
\r
22 * <p>Being an abstract class it only has generic methods for getting and setting parameters.
\r
23 * Implementing classes are supposed to create named getters and setters for convenient access
\r
24 * to parameters from the UI.</p>
\r
25 * <p>Parameters can be set with or without notifying the state manager.<p>
\r
27 * <p><i>Note: Internally the application has to be able to set parameters without state changes
\r
28 * - for instance to avoid eternal feedback when copying parameter from one state to the next. A
\r
29 * setting from the UI should spawn a new search state however.</i></p>
\r
31 * @author Niels Erik
\r
34 public abstract class Pazpar2Command implements Serializable {
\r
36 private static Logger logger = Logger.getLogger(Pazpar2Command.class);
\r
37 private static final long serialVersionUID = -6825491856480675917L;
\r
38 protected String name = "";
\r
39 protected Map<String,CommandParameter> parameters = new HashMap<String,CommandParameter>();
\r
41 public Pazpar2Command () {
\r
44 public void setCommandName(String name) {
\r
48 public Pazpar2Command (String name) {
\r
53 * Commands must implement this method to provide a completely detached, deep clone of
\r
56 * The clone is needed by the state manager to transfer commands with current setting
\r
57 * from one state to the next.
\r
59 * Whenever a non-standard attribute is added to a command class, the copy method must
\r
60 * be updated to ensure that the new attribute is brought over as well.
\r
62 * @return a Pazpar2 command of the given type
\r
64 public abstract Pazpar2Command copy ();
\r
66 public String getCommandName() {
\r
71 * Executes the command with the currently selected parameters against
\r
72 * the currently selected Pazpar2 service
\r
74 * @return Response data object based on the Pazpar2 service response.
\r
76 public ResponseDataObject run() {
\r
77 return run(Pz2Service.get().getSearchClient(),
\r
78 Pz2Service.get().getPzresp());
\r
82 * Executes the commands with the currently selected parameters, while adding
\r
83 * the parameters provided in the vararg
\r
84 * @param parameters A list of parameters on the form [key=value]
\r
86 * @return Response data object based on the Pazpar2 service response
\r
88 public ResponseDataObject runWith(String... parameters) {
\r
89 for (String parameter : parameters) {
\r
90 StringTokenizer tokenizer = new StringTokenizer(parameter,"=");
\r
91 String name = (String) tokenizer.nextElement();
\r
92 String value = (String) tokenizer.nextElement();
\r
93 CommandParameter commandParameter = new CommandParameter(name,"=",value);
\r
94 setParameterInState(commandParameter);
\r
100 * Executes the commands with the currently selected parameters, while adding
\r
101 * the parameters provided in the 'delimiter'-separated String.
\r
103 * Note: This is for Glassfish/JBoss support. With Tomcat7 the method
\r
104 * runWith(String... parameters) can be used directly from EL
\r
107 * @param parameters A list of parameters separated by 'delimiter'
\r
108 * @param delimiter The separator character of the String 'parameters'
\r
110 * @return Response data object based on the Pazpar2 service response
\r
112 public ResponseDataObject runWith2(String parameters, String delimiter) {
\r
113 StringTokenizer params = new StringTokenizer(parameters,delimiter);
\r
114 String[] vararg = new String[params.countTokens()];
\r
116 while (params.hasMoreTokens()) {
\r
117 vararg[i++] = params.nextToken();
\r
119 return runWith(vararg);
\r
123 * Executes the command in a thread.
\r
125 * Note: Client and Responses must be provided because at this point
\r
126 * CDI beans cannot be retrieved from within a thread.
\r
132 public ResponseDataObject run(SearchClient client,Responses pzresp) {
\r
133 logger.debug("Running " + getCommandName() + " using " + client);
\r
134 HttpResponseWrapper httpResponse = client.executeCommand(this);
\r
135 logger.debug("Parsing response for " + getCommandName());
\r
136 ResponseDataObject responseObject = ResponseParser.getParser().getDataObject((ClientCommandResponse) httpResponse);
\r
137 logger.trace("Storing response for " + getCommandName());
\r
138 pzresp.put(getCommandName(), responseObject);
\r
139 return responseObject;
\r
144 * Sets a parameter on this command and notifies the state manager
\r
147 * @param parameter
\r
149 public void setParameter (CommandParameter parameter) {
\r
150 Pazpar2Command copy = this.copy();
\r
151 logger.trace(name + " command: setting parameter [" + parameter.getName() + "=" + parameter.getValueWithExpressions() + "]");
\r
152 copy.parameters.put(parameter.getName(),parameter);
\r
153 checkInState(copy);
\r
157 * Sets multiple parameters on the command and notifies the state
\r
158 * manager -- once -- about the change
\r
162 public void setParameters (CommandParameter... params) {
\r
163 Pazpar2Command copy = this.copy();
\r
164 for (CommandParameter param : params) {
\r
165 logger.trace(name + " command: setting parameter [" + param.getName() + "=" + param.getValueWithExpressions() + "]");
\r
166 copy.parameters.put(param.getName(),param);
\r
168 checkInState(copy);
\r
172 * Sets multiple parameters on this command without notifying the state manager.
\r
173 * Typically used when one parameter setting should automatically trigger
\r
174 * other parameters to be reset to defaults etc. Intended to avoid
\r
175 * useless proliferation of states
\r
179 public void setParametersInState (CommandParameter... params) {
\r
180 for (CommandParameter param : params) {
\r
181 logger.trace(name + " command: setting parameter [" + param.getName() + "=" + param.getValueWithExpressions() + "] silently");
\r
182 parameters.put(param.getName(),param);
\r
187 * Sets a parameter on this command without notifying the state manager.
\r
188 * Typically used when one parameter setting should automatically trigger
\r
189 * other parameters to be reset to defaults etc. Intended to avoid
\r
190 * useless proliferation of states
\r
194 public void setParameterInState (CommandParameter parameter) {
\r
195 logger.trace(name + " command: setting parameter [" + parameter.getName() + "=" + parameter.getValueWithExpressions() + "] silently");
\r
196 parameters.put(parameter.getName(),parameter);
\r
201 * Retrieves a command parameter by parameter name
\r
203 * @param name of the parameter
\r
204 * @return CommandParameter
\r
206 public CommandParameter getParameter (String name) {
\r
207 return parameters.get(name);
\r
211 * Removes a parameter completely and notifies the state manager
\r
214 * @param name of the parameter to remove
\r
216 public void removeParameter (String name) {
\r
217 Pazpar2Command copy = this.copy();
\r
218 copy.parameters.remove(name);
\r
219 checkInState(copy);
\r
223 * Removes multiple parameters completely and notifies the state manager
\r
224 * -- once -- about the change
\r
226 * @param name of the parameter to remove
\r
228 public void removeParameters() {
\r
229 Pazpar2Command copy = this.copy();
\r
230 copy.parameters = new HashMap<String,CommandParameter>();
\r
231 checkInState(copy);
\r
236 * Removes all parameters without notifying the state manager. For instance
\r
237 * used in case of change of Pazpar2 service or renewed login to a service.
\r
240 public void removeParametersInState() {
\r
241 parameters = new HashMap<String,CommandParameter>();
\r
245 * Adds an expression to an ordered list of expressions on a given parameter
\r
246 * and notifies the state manager of the change
\r
248 * @param parameterName name of the parameter to add the expression to
\r
249 * @param expression
\r
251 public void addExpression(String parameterName, Expression expression) {
\r
252 Pazpar2Command copy = this.copy();
\r
253 copy.getParameter(parameterName).addExpression(expression);
\r
254 checkInState(copy);
\r
257 public void removeExpression(String parameterName, Expression expression) {
\r
258 Pazpar2Command copy = this.copy();
\r
259 copy.getParameter(parameterName).removeExpression(expression);
\r
260 checkInState(copy);
\r
263 public void removeExpressionsAfter(String parameterName, Expression expression,String... expressionFields) {
\r
264 Pazpar2Command copy = this.copy();
\r
265 copy.getParameter(parameterName).removeExpressionsAfter(expression,expressionFields);
\r
266 checkInState(copy);
\r
269 public void removeExpressions(String parameterName, String... expressionFields) {
\r
270 if (this.getParameter(parameterName) != null) {
\r
271 Pazpar2Command copy = this.copy();
\r
272 copy.getParameter(parameterName).removeExpressions(expressionFields);
\r
273 if (!getParameter(parameterName).hasValue() && !getParameter(parameterName).hasExpressions()) {
\r
274 copy.parameters.remove(parameterName);
\r
276 checkInState(copy);
\r
280 public boolean hasParameters () {
\r
281 return (parameters.keySet().size()>0);
\r
284 public boolean hasParameterValue(String parameterName) {
\r
285 return (parameters.get(parameterName) != null && (parameters.get(parameterName).hasValue()));
\r
288 public String getEncodedQueryString () {
\r
289 StringBuilder queryString = new StringBuilder("command="+name);
\r
290 for (CommandParameter parameter : parameters.values()) {
\r
291 if (parameter.hasValue() || parameter.hasExpressions()) {
\r
292 queryString.append("&"+parameter.getEncodedQueryString());
\r
295 return queryString.toString();
\r
298 public String getValueWithExpressions() {
\r
299 StringBuilder value = new StringBuilder("");
\r
300 for (CommandParameter parameter : parameters.values()) {
\r
301 if (parameter.hasValue() || parameter.hasExpressions()) {
\r
302 value.append("&" + parameter.getName() + parameter.operator + parameter.getValueWithExpressions());
\r
305 return value.toString();
\r
309 public boolean equals (Object otherCommand) {
\r
310 logger.trace("Comparing commands ["+this.toString()+"] and ["+otherCommand.toString() +"]");
\r
312 ((otherCommand instanceof Pazpar2Command)
\r
313 && this.getValueWithExpressions().equals(((Pazpar2Command) otherCommand).getValueWithExpressions()));
\r
317 public int hashCode () {
\r
318 return getValueWithExpressions().hashCode();
\r
321 public String toString () {
\r
322 return parameters.toString();
\r
325 public String getParameterValue(String parameterName) {
\r
326 return getParameter(parameterName)==null ? "" : getParameter(parameterName).getValueWithExpressions();
\r
330 public String getUrlEncodedParameterValue(String parameterName) {
\r
331 return getParameter(parameterName).getEncodedQueryString();
\r
335 public void setSession (String sessionId) {
\r
336 setParameter(new CommandParameter("session","=",sessionId));
\r
339 public String getSession() {
\r
340 return getParameterValue("session");
\r
344 * Notifies the state manager that this command changed a parameter
\r
348 protected void checkInState(Pazpar2Command command) {
\r
349 Pz2Service.get().getStateMgr().checkIn(command);
\r
353 * Implementing classes must provide their Service Proxy
\r
354 * extension command if any extension parameters exists,
\r
355 * or -- just to be polite -- 'this' if there is no
\r
356 * Service Proxy extension to the given command.
\r
359 public abstract ServiceProxyCommand getSp();
\r
362 * Here implementing commands publish whether they only
\r
363 * apply to the Service Proxy or can be executed
\r
364 * against straight Pazpar2 as well. This is convenient for a
\r
365 * UI that switches between service types either
\r
366 * deployment time or run time.
\r
368 * @return false if the command applies to straight Pazpar2
\r
370 public abstract boolean spOnly();
\r