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 an 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
\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 command in a thread.
\r
102 * Note: Client and Responses must be provided because at this point
\r
103 * CDI beans cannot be retrieved from within a thread.
\r
109 public ResponseDataObject run(SearchClient client,Responses pzresp) {
\r
110 logger.debug("Running " + getCommandName() + " using " + client);
\r
111 HttpResponseWrapper httpResponse = client.executeCommand(this);
\r
112 logger.debug("Parsing response for " + getCommandName());
\r
113 ResponseDataObject responseObject = ResponseParser.getParser().getDataObject((ClientCommandResponse) httpResponse);
\r
114 logger.trace("Storing response for " + getCommandName());
\r
115 pzresp.put(getCommandName(), responseObject);
\r
116 return responseObject;
\r
121 * Sets a parameter on this command and notifies the state manager
\r
124 * @param parameter
\r
126 public void setParameter (CommandParameter parameter) {
\r
127 Pazpar2Command copy = this.copy();
\r
128 logger.trace(name + " command: setting parameter [" + parameter.getName() + "=" + parameter.getValueWithExpressions() + "]");
\r
129 copy.parameters.put(parameter.getName(),parameter);
\r
130 checkInState(copy);
\r
134 * Sets multiple parameters on the command and notifies the state
\r
135 * manager -- once -- about the change
\r
139 public void setParameters (CommandParameter... params) {
\r
140 Pazpar2Command copy = this.copy();
\r
141 for (CommandParameter param : params) {
\r
142 logger.trace(name + " command: setting parameter [" + param.getName() + "=" + param.getValueWithExpressions() + "]");
\r
143 copy.parameters.put(param.getName(),param);
\r
145 checkInState(copy);
\r
149 * Sets multiple parameters on this command without notifying the state manager.
\r
150 * Typically used when one parameter setting should automatically trigger
\r
151 * other parameters to be reset to defaults etc. Intended to avoid
\r
152 * useless proliferation of states
\r
156 public void setParametersInState (CommandParameter... params) {
\r
157 for (CommandParameter param : params) {
\r
158 logger.trace(name + " command: setting parameter [" + param.getName() + "=" + param.getValueWithExpressions() + "] silently");
\r
159 parameters.put(param.getName(),param);
\r
164 * Sets a parameter on this command without notifying the state manager.
\r
165 * Typically used when one parameter setting should automatically trigger
\r
166 * other parameters to be reset to defaults etc. Intended to avoid
\r
167 * useless proliferation of states
\r
171 public void setParameterInState (CommandParameter parameter) {
\r
172 logger.trace(name + " command: setting parameter [" + parameter.getName() + "=" + parameter.getValueWithExpressions() + "] silently");
\r
173 parameters.put(parameter.getName(),parameter);
\r
178 * Retrieves a command parameter by parameter name
\r
180 * @param name of the parameter
\r
181 * @return CommandParameter
\r
183 public CommandParameter getParameter (String name) {
\r
184 return parameters.get(name);
\r
188 * Removes a parameter completely and notifies the state manager
\r
191 * @param name of the parameter to remove
\r
193 public void removeParameter (String name) {
\r
194 Pazpar2Command copy = this.copy();
\r
195 copy.parameters.remove(name);
\r
196 checkInState(copy);
\r
200 * Removes multiple parameters completely and notifies the state manager
\r
201 * -- once -- about the change
\r
203 * @param name of the parameter to remove
\r
205 public void removeParameters() {
\r
206 Pazpar2Command copy = this.copy();
\r
207 copy.parameters = new HashMap<String,CommandParameter>();
\r
208 checkInState(copy);
\r
213 * Removes all parameters without notifying the state manager. For instance
\r
214 * used in case of change of Pazpar2 service or renewed login to a service.
\r
217 public void removeParametersInState() {
\r
218 parameters = new HashMap<String,CommandParameter>();
\r
222 * Adds an expression to an ordered list of expressions on a given parameter
\r
223 * and notifies the state manager of the change
\r
225 * @param parameterName name of the parameter to add the expression to
\r
226 * @param expression
\r
228 public void addExpression(String parameterName, Expression expression) {
\r
229 Pazpar2Command copy = this.copy();
\r
230 copy.getParameter(parameterName).addExpression(expression);
\r
231 checkInState(copy);
\r
234 public void removeExpression(String parameterName, Expression expression) {
\r
235 Pazpar2Command copy = this.copy();
\r
236 copy.getParameter(parameterName).removeExpression(expression);
\r
237 checkInState(copy);
\r
240 public void removeExpressionsAfter(String parameterName, Expression expression,String... expressionFields) {
\r
241 Pazpar2Command copy = this.copy();
\r
242 copy.getParameter(parameterName).removeExpressionsAfter(expression,expressionFields);
\r
243 checkInState(copy);
\r
246 public void removeExpressions(String parameterName, String... expressionFields) {
\r
247 Pazpar2Command copy = this.copy();
\r
248 copy.getParameter(parameterName).removeExpressions(expressionFields);
\r
249 if (!getParameter(parameterName).hasValue() && !getParameter(parameterName).hasExpressions()) {
\r
250 copy.parameters.remove(parameterName);
\r
252 checkInState(copy);
\r
255 public boolean hasParameters () {
\r
256 return (parameters.keySet().size()>0);
\r
259 public boolean hasParameterValue(String parameterName) {
\r
260 return (parameters.get(parameterName) != null && (parameters.get(parameterName).hasValue()));
\r
263 public String getEncodedQueryString () {
\r
264 StringBuilder queryString = new StringBuilder("command="+name);
\r
265 for (CommandParameter parameter : parameters.values()) {
\r
266 if (parameter.hasValue() || parameter.hasExpressions()) {
\r
267 queryString.append("&"+parameter.getEncodedQueryString());
\r
270 return queryString.toString();
\r
273 public String getValueWithExpressions() {
\r
274 StringBuilder value = new StringBuilder("");
\r
275 for (CommandParameter parameter : parameters.values()) {
\r
276 if (parameter.hasValue() || parameter.hasExpressions()) {
\r
277 value.append("&" + parameter.getName() + parameter.operator + parameter.getValueWithExpressions());
\r
280 return value.toString();
\r
284 public boolean equals (Object otherCommand) {
\r
285 logger.trace("Comparing commands ["+this.toString()+"] and ["+otherCommand.toString() +"]");
\r
287 ((otherCommand instanceof Pazpar2Command)
\r
288 && this.getValueWithExpressions().equals(((Pazpar2Command) otherCommand).getValueWithExpressions()));
\r
292 public int hashCode () {
\r
293 return getValueWithExpressions().hashCode();
\r
296 public String toString () {
\r
297 return parameters.toString();
\r
300 public String getParameterValue(String parameterName) {
\r
301 return getParameter(parameterName)==null ? "" : getParameter(parameterName).getValueWithExpressions();
\r
305 public String getUrlEncodedParameterValue(String parameterName) {
\r
306 return getParameter(parameterName).getEncodedQueryString();
\r
310 public void setSession (String sessionId) {
\r
311 setParameter(new CommandParameter("session","=",sessionId));
\r
314 public String getSession() {
\r
315 return getParameterValue("session");
\r
319 * Notifies the state manager that this command changed a parameter
\r
323 protected void checkInState(Pazpar2Command command) {
\r
324 Pz2Service.get().getStateMgr().checkIn(command);
\r
328 * Implementing classes must provide their Service Proxy
\r
329 * extension command if any extension parameters exists,
\r
330 * or -- just to be polite -- 'this' if there is no
\r
331 * Service Proxy extension to the given command.
\r
334 public abstract ServiceProxyCommand getSp();
\r
337 * Implementing commands publishes whether they only
\r
338 * apply to the Service Proxy - or can be executed
\r
339 * against straight Pazpar2 as well. Convenient for a
\r
340 * UI that switches between service types - whether
\r
341 * deployment time or run time.
\r
343 * @return false if the command applies to straight Pazpar2
\r
345 public abstract boolean spOnly();
\r