source: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUSearchRetrieveRequest.java @ 7266

Last change on this file since 7266 was 7266, checked in by Oliver Schonefeld, 2 years ago
  • re-factor to make SRUOperation available
  • add experimental support for processing authenticated requests
  • Property svn:eol-style set to native
File size: 15.5 KB
Line 
1/**
2 * This software is copyright (c) 2012-2016 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;
20
21/**
22 * An object for performing a <em>searchRetrieve</em> operation.
23 * <p>
24 * The following argument arguments are mandatory:
25 * </p>
26 * <ul>
27 * <li><em>query</em></li>
28 * <li><em>queryType</em>, if using query language other than CQL (only SRU 2.0)</li>
29 * </ul>
30 *
31 * @see SRUSearchRetrieveHandler
32 * @see <a href="http://www.loc.gov/standards/sru/specs/search-retrieve.html">
33 *      SRU SearchRetrieve Operation</a>
34 */
35public class SRUSearchRetrieveRequest extends SRUAbstractRequest {
36    /** for end-point conformance testing only. never use in production. */
37    public static final String X_MALFORMED_QUERY =
38            "x-malformed-query";
39    /** for end-point conformance testing only. never use in production. */
40    public static final String X_MALFORMED_START_RECORD =
41            "x-malformed-startRecord";
42    /** for end-point conformance testing only. never use in production. */
43    public static final String X_MALFORMED_MAXIMUM_RECORDS =
44            "x-malformed-maximumRecords";
45    /** for end-point conformance testing only. never use in production. */
46    public static final String X_MALFORMED_RECORD_XML_ESCAPING =
47            "x-malformed-recordPacking";
48    private String queryType;
49    private String query;
50    private int startRecord = -1;
51    private int maximumRecords = -1;
52    private SRURecordXmlEscaping recordXmlEscaping;
53    private SRURecordPacking recordPacking;
54    private String recordSchema;
55    private int resultSetTTL = -1;
56
57
58    /**
59     * Constructor.
60     *
61     * @param baseURI
62     *            the baseURI of the endpoint
63     */
64    public SRUSearchRetrieveRequest(URI baseURI) {
65        super(baseURI);
66    }
67
68
69    /**
70     * Constructor.
71     *
72     * @param baseURI
73     *            the baseURI of the endpoint
74     */
75    public SRUSearchRetrieveRequest(String baseURI) {
76        super(baseURI);
77    }
78
79
80    /**
81     * (SRU 2.0) Get the value of the <em>queryType</em> argument for this
82     * request.
83     *
84     * @return the value for the <em>queryType</em> argument or
85     *         <code>null</code> of none was set
86     */
87    public String getQueryType() {
88        return queryType;
89    }
90
91
92    /**
93     * Get the value of the <em>query</em> argument for this request.
94     *
95     * @return the value for the <em>query</em> argument or <code>null</code> of
96     *         none was set
97     */
98    public String getQuery() {
99        return query;
100    }
101
102
103    /**
104     * Set the value of the <em>queryType</em> (SRU 2.0) and the <em>query</em>
105     * argument for this request.
106     * <p>
107     * For SRU 1.1 and SRU 1.2 requests use the following:</p>
108     * <pre>
109     * {@code
110     * String cql_query = ...
111     * SRUSearchRetrieveRequest req =
112     *      new SRUSearchRetrieveRequest("http://endpoint.example.org");
113     * req.setQuery(SRUClientConstants.QUERY_TYPE_CQL, cql_query);
114     * }
115     * </pre>
116     *
117     * @param queryType
118     *            the value for the <em>queryType</em> argument
119     * @param query
120     *            the value for the <em>query</em> argument
121     * @throws NullPointerException
122     *             if any required argument is <code>null</code>
123     * @throws IllegalArgumentException
124     *             if any argument is invalid
125     * @see SRUClientConstants#QUERY_TYPE_CQL
126     */
127    public void setQuery(String queryType, String query) {
128        if (query == null) {
129            throw new NullPointerException("query == null");
130        }
131        if (query.isEmpty()) {
132            throw new IllegalArgumentException("query is an empty string");
133        }
134        if (queryType == null) {
135            throw new NullPointerException("queryType == null");
136        }
137        if (queryType.isEmpty()) {
138            throw new IllegalArgumentException("queryType is an empty string");
139        }
140        for (int i = 0; i < queryType.length(); i++) {
141            final char ch = queryType.charAt(i);
142            if (!((ch >= 'a' && ch <= 'z') ||
143                    (ch >= 'A' && ch <= 'Z') ||
144                    (ch >= '0' && ch <= '9') ||
145                    ((i > 0) && ((ch == '-') || ch == '_')))) {
146                throw new IllegalArgumentException(
147                        "queryType contains illegal characters");
148            }
149        }
150
151        this.queryType = queryType;
152        this.query = query;
153    }
154
155
156    /**
157     * Get the value of the <em>startRecord</em> argument for this request.
158     *
159     * @return the value for the <em>startRecord</em> argument or
160     *         <code>-1</code> of none was set
161     */
162    public int getStartRecord() {
163        return startRecord;
164    }
165
166
167    /**
168     * Set the value of the <em>startRecord</em> argument for this request.
169     *
170     * @param startRecord
171     *            the value for the <em>startRecord</em> argument
172     * @throws IllegalArgumentException
173     *             if any argument is invalid
174     */
175    public void setStartRecord(int startRecord) {
176        if (startRecord < 1) {
177            throw new IllegalArgumentException("startRecord < 1");
178        }
179        this.startRecord = startRecord;
180    }
181
182
183    /**
184     * Get the value of the <em>maximumRecords</em> argument for this request.
185     *
186     * @return the value for the <em>maximumRecords</em> argument or
187     *         <code>-1</code> of none was set
188     */
189    public int getMaximumRecords() {
190        return maximumRecords;
191    }
192
193
194    /**
195     * Set the value of the <em>maximumRecords</em> argument for this request.
196     *
197     * @param maximumRecords
198     *            the value for the <em>maximumRecords</em> argument
199     * @throws IllegalArgumentException
200     *             if any argument is invalid
201     */
202    public void setMaximumRecords(int maximumRecords) {
203        if (maximumRecords < 0) {
204            throw new IllegalArgumentException("maximumRecords < 0");
205        }
206        this.maximumRecords = maximumRecords;
207    }
208
209
210    /**
211     * Get the value of the <em>recordSchema</em> argument for this request.
212     *
213     * @return the value for the <em>recordSchema</em> argument or
214     *         <code>null</code> of none was set
215     */
216    public String getRecordSchema() {
217        return recordSchema;
218    }
219
220
221    /**
222     * Set the value of the <em>recordSchema</em> argument for this request.
223     *
224     * @param recordSchema
225     *            the value for the <em>recordSchema</em> argument
226     * @throws NullPointerException
227     *             if any required argument is <code>null</code>
228     * @throws IllegalArgumentException
229     *             if any argument is invalid
230     */
231    public void setRecordSchema(String recordSchema) {
232        this.recordSchema = recordSchema;
233    }
234
235
236    /**
237     * Get the <em>recordXmlEscpaing</em> (SRU 2.0) or <em>recordPacking</em>
238     * (SRU 1.1 and SRU 1.2) parameter of this request.
239     *
240     * @return the requested record XML escaping
241     * @see SRURecordXmlEscaping
242     */
243    public SRURecordXmlEscaping getRecordXmlEscaping() {
244        return recordXmlEscaping;
245    }
246
247
248    /**
249     * Set the <em>recordXmlEscpaing</em> (SRU 2.0) or <em>recordPacking</em>
250     * (SRU 1.1 and SRU 1.2) parameter of this request.
251     *
252     * @param recordXmlEscaping
253     *            the requested record XML escaping
254     * @see SRURecordXmlEscaping
255     */
256    public void setRecordXmlEscaping(SRURecordXmlEscaping recordXmlEscaping) {
257        if (recordXmlEscaping == null) {
258            throw new NullPointerException("recordXmlEscaping == null");
259        }
260        this.recordXmlEscaping = recordXmlEscaping;
261    }
262
263
264    /**
265     * Get the <em>recordPacking</em> (SRU 2.0) parameter of this request.
266     *
267     * @return the requested record packing
268     * @see SRURecordPacking
269     */
270    public SRURecordPacking getRecordPacking() {
271        return recordPacking;
272    }
273
274
275    /**
276     * Set the <em>recordPacking</em> (SRU 2.0) parameter of this request.
277     *
278     * @param recordPacking
279     *            the requested recordPacking mode
280     * @see SRURecordXmlEscaping
281     */
282    public void setRecordPacking(SRURecordPacking recordPacking) {
283        if (recordPacking == null) {
284            throw new NullPointerException("recordPacking == null");
285        }
286        this.recordPacking = recordPacking;
287    }
288
289
290    /**
291     * Get the value of the <em>resultSetTTL</em> argument for this request.
292     *
293     * @return the value for the <em>resultSetTTL</em> argument or
294     *         <code>-1</code> of none was set
295     */
296    public int getResultSetTTL() {
297        return resultSetTTL;
298    }
299
300
301    /**
302     * Set the value of the <em>resultSetTTL</em> argument for this request.
303     *
304     * @param resultSetTTL
305     *            the value for the <em>resultSetTTL</em> argument
306     * @throws IllegalArgumentException
307     *             if any argument is invalid
308     */
309    public void setResultSetTTL(int resultSetTTL) {
310        this.resultSetTTL = resultSetTTL;
311    }
312
313
314    @Override
315    public SRUOperation getOperation() {
316        return SRUOperation.SEARCH_RETRIEVE;
317    }
318
319
320    @Override
321    void addParametersToURI(URIHelper uriHelper, SRUVersion version)
322            throws SRUClientException {
323        /*
324         * append query argument (mandatory)
325         *
326         * NB: Setting "x-malformed-query" as an extra request parameter makes
327         * the client to send invalid requests. This is intended to use for
328         * testing endpoints for protocol conformance (i.e. provoke an error)
329         * and SHOULD NEVER be used in production!
330         */
331        final String malformedQuery = getExtraRequestData(X_MALFORMED_QUERY);
332        if (malformedQuery == null) {
333            if ((query == null) || query.isEmpty()) {
334                throw new SRUClientException(
335                        "mandatory argument 'query' not set or empty");
336            }
337            uriHelper.append(PARAM_QUERY, query);
338        } else {
339            if (!malformedQuery.equalsIgnoreCase(MALFORMED_OMIT)) {
340                uriHelper.append(PARAM_QUERY, malformedQuery);
341            }
342        }
343
344        /*
345         * append queryType parameter (SRU 2.0, optional)
346         */
347        if ((version == SRUVersion.VERSION_2_0) && (queryType != null)) {
348            if (!SRUClientConstants.QUERY_TYPE_CQL.equals(queryType)) {
349                uriHelper.append(PARAM_QUERY_TYPE, queryType);
350            }
351        }
352
353        /*
354         * append startRecord argument (optional)
355         *
356         * NB: Setting "x-malformed-startRecord" as an extra request parameter
357         * makes the client to send invalid requests. This is intended to use
358         * for testing endpoints for protocol conformance (i.e. provoke an
359         * error) and SHOULD NEVER be used in production!
360         */
361        final String malformedStartRecord =
362                getExtraRequestData(X_MALFORMED_START_RECORD);
363        if (malformedStartRecord == null) {
364            if (startRecord > 0) {
365                uriHelper.append(PARAM_START_RECORD, startRecord);
366            }
367        } else {
368            if (!malformedStartRecord.equalsIgnoreCase(MALFORMED_OMIT)) {
369                uriHelper.append(PARAM_START_RECORD, malformedStartRecord);
370            }
371        }
372
373        /*
374         * append maximumRecords argument (optional)
375         *
376         * NB: Setting "x-malformed-maximumRecords" as an extra request
377         * parameter makes the client to send invalid requests. This is
378         * intended to use for testing endpoints for protocol conformance
379         * (i.e. provoke an error) and SHOULD NEVER be used in production!
380         */
381        final String malformedMaxiumRecords =
382                getExtraRequestData(X_MALFORMED_MAXIMUM_RECORDS);
383        if (malformedMaxiumRecords == null) {
384            if (maximumRecords > -1) {
385                uriHelper.append(PARAM_MAXIMUM_RECORDS, maximumRecords);
386            }
387        } else {
388            if (!malformedMaxiumRecords.equalsIgnoreCase(MALFORMED_OMIT)) {
389                uriHelper.append(PARAM_MAXIMUM_RECORDS,
390                        malformedMaxiumRecords);
391            }
392        }
393
394        /*
395         * append record XML escaping argument (optional)
396         *
397         * NB: Setting "x-malformed-recordPacking" as an extra request
398         * parameter makes the client to send invalid requests. This is
399         * intended to use for testing endpoints for protocol conformance
400         * (i.e. provoke an error) and SHOULD NEVER be used in production!
401         */
402        final String malformedRecordXmlEscaping =
403                getExtraRequestData(X_MALFORMED_RECORD_XML_ESCAPING);
404        if (malformedRecordXmlEscaping == null) {
405            if (recordXmlEscaping != null) {
406                switch (recordXmlEscaping) {
407                case XML:
408                    if (version == SRUVersion.VERSION_2_0) {
409                        uriHelper.append(PARAM_RECORD_XML_ESCAPING,
410                                RECORD_XML_ESCAPING_XML);
411                    } else {
412                        uriHelper.append(PARAM_RECORD_PACKING,
413                                RECORD_XML_ESCAPING_XML);
414                    }
415                    break;
416                case STRING:
417                    if (version == SRUVersion.VERSION_2_0) {
418                        uriHelper.append(PARAM_RECORD_XML_ESCAPING,
419                                RECORD_XML_ESCPAING_STRING);
420                    } else {
421                        uriHelper.append(PARAM_RECORD_PACKING,
422                                RECORD_XML_ESCPAING_STRING);
423                    }
424                    break;
425                default:
426                    throw new SRUClientException("internal error: invalid " +
427                            "recordXmlEscaping (" + recordXmlEscaping + ")");
428                } // switch
429            }
430        } else {
431            if (!malformedRecordXmlEscaping.equalsIgnoreCase(MALFORMED_OMIT)) {
432                if (version == SRUVersion.VERSION_2_0) {
433                    uriHelper.append(PARAM_RECORD_XML_ESCAPING,
434                            malformedRecordXmlEscaping);
435                } else {
436                    uriHelper.append(PARAM_RECORD_PACKING,
437                            malformedRecordXmlEscaping);
438                }
439            }
440        }
441
442        /*
443         * (SRU 2.0) append recordPacking argument (optional)
444         */
445        if ((version == SRUVersion.VERSION_2_0) && (recordPacking != null)) {
446            switch (recordPacking) {
447            case PACKED:
448                uriHelper.append(PARAM_RECORD_PACKING, RECORD_PACKING_PACKED);
449                break;
450            case UNPACKED:
451                uriHelper.append(PARAM_RECORD_PACKING, RECORD_PACKING_UNPACKED);
452                break;
453            default:
454                throw new SRUClientException("internal error: invalid value " +
455                        "for recordPacking (" + recordPacking + ")");
456            }
457        }
458
459        /*
460         * append recordSchema argument (optional)
461         */
462        if (recordSchema != null) {
463            uriHelper.append(PARAM_RECORD_SCHEMA, recordSchema);
464        }
465
466        /*
467         * append resultSetTTL argument (optional)
468         */
469        if (resultSetTTL > -1) {
470            uriHelper.append(PARAM_RESULT_SET_TTL, resultSetTTL);
471        }
472    }
473
474} // class SRUSearchRetrieveRequest
Note: See TracBrowser for help on using the repository browser.