source: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUAbstractRequest.java @ 5804

Last change on this file since 5804 was 5804, checked in by Oliver Schonefeld, 10 years ago
  • some javadoc and other miscellaneous stuff
  • Property svn:eol-style set to native
File size: 13.7 KB
Line 
1/**
2 * This software is copyright (c) 2012-2014 by
3 *  - Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
4 * This is free software. You can redistribute it
5 * and/or modify it under the terms described in
6 * the GNU General Public License v3 of which you
7 * should have received a copy. Otherwise you can download
8 * it from
9 *
10 *   http://www.gnu.org/licenses/gpl-3.0.txt
11 *
12 * @copyright Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
13 *
14 * @license http://www.gnu.org/licenses/gpl-3.0.txt
15 *  GNU General Public License v3
16 */
17package eu.clarin.sru.client;
18
19import java.net.URI;
20import java.net.URISyntaxException;
21import java.util.HashMap;
22import java.util.Map;
23
24import org.apache.http.client.utils.URIBuilder;
25
26
27
28/**
29 * Abstract base class for SRU requests.
30 *
31 * @see SRUExplainResponse
32 * @see SRUScanResponse
33 * @see SRUSearchRetrieveResponse
34 */
35abstract class SRUAbstractRequest {
36    static final String PARAM_OPERATION                = "operation";
37    static final String PARAM_VERSION                  = "version";
38    static final String PARAM_RECORD_PACKING           = "recordPacking";
39    static final String PARAM_STYLESHEET               = "stylesheet";
40    static final String PARAM_QUERY                    = "query";
41    static final String PARAM_START_RECORD             = "startRecord";
42    static final String PARAM_MAXIMUM_RECORDS          = "maximumRecords";
43    static final String PARAM_RECORD_SCHEMA            = "recordSchema";
44    static final String PARAM_RECORD_X_PATH            = "recordXPath";
45    static final String PARAM_RESULT_SET_TTL           = "resultSetTTL";
46    static final String PARAM_SORT_KEYS                = "sortKeys";
47    static final String PARAM_SCAN_CLAUSE              = "scanClause";
48    static final String PARAM_RESPONSE_POSITION        = "responsePosition";
49    static final String PARAM_MAXIMUM_TERMS            = "maximumTerms";
50    static final String RECORD_PACKING_XML             = "xml";
51    static final String RECORD_PACKING_STRING          = "string";
52    private static final String OP_EXPLAIN             = "explain";
53    private static final String OP_SCAN                = "scan";
54    private static final String OP_SEARCH_RETRIEVE     = "searchRetrieve";
55    private static final String VERSION_1_1            = "1.1";
56    private static final String VERSION_1_2            = "1.2";
57    private static final String PARAM_EXTENSION_PREFIX = "x-";
58    /** for end-point conformance testing only. never use in production. */
59    public static final String X_MALFORMED_OPERATION   =
60            "x-malformed-operation";
61    /** for end-point conformance testing only. never use in production. */
62    public static final String X_MALFORMED_VERSION     =
63            "x-malformed-version";
64    /** for end-point conformance testing only. never use in production. */
65    public static final String MALFORMED_OMIT          = "omit";
66    private static final String MALFORMED_KEY_PREFIX   = "x-malformed";
67
68
69    enum SRUOperation {
70        EXPLAIN, SCAN, SEARCH_RETRIEVE
71    } // enum SRUOperation
72
73
74    static class URIHelper {
75        private final URIBuilder uriBuilder;
76
77
78        private URIHelper(URIBuilder builder) {
79            this.uriBuilder = builder;
80        }
81
82
83        public URIHelper append(String name, String value) {
84            if (name == null) {
85                throw new NullPointerException("name == null");
86            }
87            if (name.isEmpty()) {
88                throw new IllegalArgumentException("name is empty");
89            }
90            if (value == null) {
91                throw new NullPointerException("value == null");
92            }
93            if (value.isEmpty()) {
94                throw new IllegalArgumentException("value is empty");
95            }
96
97            uriBuilder.addParameter(name, value);
98            return this;
99        }
100
101
102        public URIHelper append(String name, int value) {
103            return append(name, Integer.toString(value));
104        }
105
106
107        private URI makeURI() throws URISyntaxException {
108            return uriBuilder.build();
109        }
110    } // class URIHelper
111    /** The baseURI of the SRU server. */
112    protected final URI baseURI;
113    /**
114     * The request should be processed in strict or non-strict SRU protocol
115     * conformance mode. Default value is <code>true</code>.
116     */
117    private boolean strictMode = true;
118    /** The version to be used for this request. */
119    protected SRUVersion version;
120    /** A map of extra request data parameters. */
121    protected Map<String, String> extraRequestData;
122    private SRUVersion versionPerformed;
123
124
125    /**
126     * Constructor.
127     *
128     * @param baseURI
129     *            the baseURI of the SRU server
130     * @throws NullPointerException
131     *             if any required argument is null
132     */
133    protected SRUAbstractRequest(URI baseURI) {
134        if (baseURI == null) {
135            throw new NullPointerException("baseURI == null");
136        }
137        this.baseURI = baseURI;
138    }
139
140
141    /**
142     * Constructor.
143     *
144     * @param baseURI
145     *            the baseURI of the SRU server
146     * @throws NullPointerException
147     *             if any required argument is null
148     * @throw IllegalArgumentException if the URI is invalid
149     */
150    protected SRUAbstractRequest(String baseURI) {
151        if (baseURI == null) {
152            throw new NullPointerException("baseURI == null");
153        }
154        if (baseURI.isEmpty()) {
155            throw new IllegalArgumentException("baseURI is empty");
156        }
157        try {
158            this.baseURI = new URI(baseURI);
159        } catch (URISyntaxException e) {
160            throw new IllegalArgumentException("invalid URI", e);
161        }
162    }
163
164
165    /**
166     * Get the baseURI of the SRU server.
167     *
168     * @return the baseURI of the SRU server
169     */
170    public URI getBaseURI() {
171        return baseURI;
172    }
173
174
175    /**
176     * Get the SRU protocol conformance mode for this request
177     *
178     * @return <code>true</code> if the request will be performed in strict
179     *         mode, <code>false</code> if the request will be performed in a
180     *         more tolerant mode
181     */
182    public boolean isStrictMode() {
183        return strictMode;
184    }
185
186
187    /**
188     * Set the SRU protocol conformance mode for this request
189     *
190     * @param strictMode
191     *            <code>true</code> if the request should be performed in strict
192     *            mode, <code>false</code> if the request should be performed
193     *            client should in a more tolerant mode
194     */
195    public void setStrictMode(boolean strictMode) {
196        this.strictMode = strictMode;
197    }
198
199
200    /**
201     * Set the version for this request.
202     *
203     * @param version a version of <code>null</code> for client default
204     */
205    public void setVersion(SRUVersion version) {
206        this.version = version;
207    }
208
209
210    /**
211     * Get the version for this request.
212     *
213     * @return version for this request or <code>null</code> of client default
214     *         is used
215     */
216    public SRUVersion getVersion() {
217        return version;
218    }
219
220
221    /**
222     * Set an extra request parameter for this request.
223     *
224     * @param name
225     *            the name for the extra request data parameter
226     * @param value
227     *            the value for the extra request data parameter
228     * @throws NullPointerException
229     *             if any required argument is <code>null</code>
230     * @throws IllegalArgumentException
231     *             if any argument is invalid
232     * @see <a href="http://www.loc.gov/standards/sru/specs/extra-data.html">SRU
233     *      Extra Data / Extensions</a>
234     */
235    public void setExtraRequestData(String name, String value) {
236        if (name == null) {
237            throw new NullPointerException("name == null");
238        }
239        if (name.isEmpty()) {
240            throw new IllegalArgumentException("name is an empty string");
241        }
242        if (!name.startsWith(PARAM_EXTENSION_PREFIX)) {
243            throw new IllegalArgumentException("name must start with '" +
244                    PARAM_EXTENSION_PREFIX + "'");
245        }
246        if (value == null) {
247            throw new NullPointerException("value == null");
248        }
249        if (value.isEmpty()) {
250            throw new IllegalArgumentException("value is an empty string");
251        }
252        if (extraRequestData == null) {
253            extraRequestData = new HashMap<String, String>();
254        }
255        extraRequestData.put(name, value);
256    }
257
258
259    /**
260     * Set the value of extra request parameter for this request.
261     *
262     * @param name
263     *            the name for the extra request data parameter
264     * @return the value for the extra request data parameter or
265     *         <code>null</code> if parameter was not set
266     * @throws NullPointerException
267     *             if any required argument is <code>null</code>
268     * @throws IllegalArgumentException
269     *             if any argument is invalid
270     * @see <a href="http://www.loc.gov/standards/sru/specs/extra-data.html">SRU
271     *      Extra Data / Extensions</a>
272     */
273    public String getExtraRequestData(String name) {
274        if (name == null) {
275            throw new NullPointerException("name == null");
276        }
277        if (name.isEmpty()) {
278            throw new IllegalArgumentException("name is an empty string");
279        }
280        if (!name.startsWith(PARAM_EXTENSION_PREFIX)) {
281            throw new IllegalArgumentException("name must start with '" +
282                    PARAM_EXTENSION_PREFIX + "'");
283        }
284        if (extraRequestData != null) {
285            return extraRequestData.get(name);
286        }
287        return null;
288    }
289
290
291    final SRUVersion getVersionPerformed() {
292        return versionPerformed;
293    }
294
295
296    final URI makeURI(SRUVersion defaultVersion)
297            throws SRUClientException {
298        if (defaultVersion == null) {
299            throw new NullPointerException("defaultVersion == null");
300        }
301
302        try {
303            final URIHelper uriBuilder =
304                    new URIHelper(new URIBuilder(baseURI));
305
306            /*
307             * append operation parameter
308             *
309             * NB: Setting "x-malformed-operation" as an extra request parameter
310             * makes the client to send invalid requests. This is intended to
311             * use for testing SRU servers for protocol conformance (i.e.
312             * provoke an error) and SHOULD NEVER be used in production!
313             */
314            final String malformedOperation =
315                    getExtraRequestData(X_MALFORMED_OPERATION);
316            if (malformedOperation == null) {
317                switch (getOperation()) {
318                case EXPLAIN:
319                    uriBuilder.append(PARAM_OPERATION, OP_EXPLAIN);
320                    break;
321                case SCAN:
322                    uriBuilder.append(PARAM_OPERATION, OP_SCAN);
323                    break;
324                case SEARCH_RETRIEVE:
325                    uriBuilder.append(PARAM_OPERATION, OP_SEARCH_RETRIEVE);
326                    break;
327                default:
328                    throw new SRUClientException("unsupported operation: " +
329                            getOperation());
330                } // switch
331            } else {
332                if (!malformedOperation.equals(MALFORMED_OMIT)) {
333                    uriBuilder.append(PARAM_OPERATION, malformedOperation);
334                }
335            }
336
337            /*
338             * append version parameter
339             *
340             * NB: Setting "x-malformed-version" as an extra request parameter
341             * makes the client to send invalid requests. This is intended to
342             * use for testing SRU servers for protocol conformance (i.e.
343             * provoke an error) and SHOULD NEVER be used in production!
344             */
345            final String malformedVersion =
346                    getExtraRequestData(X_MALFORMED_VERSION);
347            if (malformedVersion == null) {
348                versionPerformed = (version != null) ? version : defaultVersion;
349                switch (versionPerformed) {
350                case VERSION_1_1:
351                    uriBuilder.append(PARAM_VERSION, VERSION_1_1);
352                    break;
353                case VERSION_1_2:
354                    uriBuilder.append(PARAM_VERSION, VERSION_1_2);
355                    break;
356                default:
357                    throw new SRUClientException("unsupported version: " +
358                            versionPerformed);
359                } // switch
360            } else {
361                if (!malformedVersion.equalsIgnoreCase(MALFORMED_OMIT)) {
362                    uriBuilder.append(PARAM_VERSION, malformedVersion);
363                }
364            }
365
366            // request specific parameters
367            addParametersToURI(uriBuilder);
368
369            // extraRequestData
370            if ((extraRequestData != null) && !extraRequestData.isEmpty()) {
371                for (Map.Entry<String, String> entry :
372                    extraRequestData.entrySet()) {
373                    final String key = entry.getKey();
374
375                    /*
376                     * make sure, we skip the client-internal parameters
377                     * to generate invalid requests ...
378                     */
379                    if (!key.startsWith(MALFORMED_KEY_PREFIX)) {
380                        uriBuilder.append(key, entry.getValue());
381                    }
382                }
383            }
384
385            return uriBuilder.makeURI();
386        } catch (URISyntaxException e) {
387            throw new SRUClientException("error while building request URI", e);
388        }
389    }
390
391
392    /**
393     * <em>Note: this method is not a part of public API.</em>
394     * @return a operation constant for this request
395     */
396    abstract SRUOperation getOperation();
397
398
399    abstract void addParametersToURI(URIHelper uriBuilder)
400            throws SRUClientException;
401
402} // class SRUAbstractRequest
Note: See TracBrowser for help on using the repository browser.