001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.solr.request;
017:
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import java.util.Map;
021:
022: import org.apache.solr.core.SolrException;
023: import org.apache.solr.util.NamedList;
024: import org.apache.solr.util.SimpleOrderedMap;
025:
026: /** SolrParams hold request parameters.
027: *
028: * @author yonik
029: * @version $Id$
030: */
031: public abstract class SolrParams {
032: /** the query type - which query handler should handle the request */
033: public static final String QT = "qt";
034: /** the response writer type - the format of the response */
035: public static final String WT = "wt";
036: /** query string */
037: public static final String Q = "q";
038: /** sort order */
039: public static final String SORT = "sort";
040: /** Lucene query string(s) for filtering the results without affecting scoring */
041: public static final String FQ = "fq";
042: /** zero based offset of matching documents to retrieve */
043: public static final String START = "start";
044: /** number of documents to return starting at "start" */
045: public static final String ROWS = "rows";
046: /** stylesheet to apply to XML results */
047: public static final String XSL = "xsl";
048: /** stylesheet to apply to XML results */
049: public static final String VERSION = "version";
050: /** query and init param for field list */
051: public static final String FL = "fl";
052: /** default query field */
053: public static final String DF = "df";
054: /** whether to include debug data */
055: public static final String DEBUG_QUERY = "debugQuery";
056: /** another query to explain against */
057: public static final String EXPLAIN_OTHER = "explainOther";
058:
059: /**
060: * Should facet counts be calculated?
061: */
062: public static final String FACET = "facet";
063:
064: /**
065: * Any lucene formated queries the user would like to use for
066: * Facet Contraint Counts (multi-value)
067: */
068: public static final String FACET_QUERY = "facet.query";
069: /**
070: * Any field whose terms the user wants to enumerate over for
071: * Facet Contraint Counts (multi-value)
072: */
073: public static final String FACET_FIELD = "facet.field";
074:
075: /**
076: * The offset into the list of facets.
077: * Can be overriden on a per field basis.
078: */
079: public static final String FACET_OFFSET = "facet.offset";
080:
081: /**
082: * Numeric option indicating the maximum number of facet field counts
083: * be included in the response for each field - in descending order of count.
084: * Can be overriden on a per field basis.
085: */
086: public static final String FACET_LIMIT = "facet.limit";
087:
088: /**
089: * Numeric option indicating the minimum number of hits before a facet should
090: * be included in the response. Can be overriden on a per field basis.
091: */
092: public static final String FACET_MINCOUNT = "facet.mincount";
093:
094: /**
095: * Boolean option indicating whether facet field counts of "0" should
096: * be included in the response. Can be overriden on a per field basis.
097: */
098: public static final String FACET_ZEROS = "facet.zeros";
099:
100: /**
101: * Boolean option indicating whether the response should include a
102: * facet field count for all records which have no value for the
103: * facet field. Can be overriden on a per field basis.
104: */
105: public static final String FACET_MISSING = "facet.missing";
106:
107: /**
108: * Boolean option: true causes facets to be sorted
109: * by the count, false results in natural index order.
110: */
111: public static final String FACET_SORT = "facet.sort";
112:
113: /**
114: * Only return constraints of a facet field with the given prefix.
115: */
116: public static final String FACET_PREFIX = "facet.prefix";
117:
118: /**
119: * When faceting by enumerating the terms in a field,
120: * only use the filterCache for terms with a df >= to this parameter.
121: */
122: public static final String FACET_ENUM_CACHE_MINDF = "facet.enum.cache.minDf";
123:
124: /** If the content stream should come from a URL (using URLConnection) */
125: public static final String STREAM_URL = "stream.url";
126:
127: /** If the content stream should come from a File (using FileReader) */
128: public static final String STREAM_FILE = "stream.file";
129:
130: /** If the content stream should come directly from a field */
131: public static final String STREAM_BODY = "stream.body";
132:
133: /**
134: * Explicity set the content type for the input stream
135: * If multiple streams are specified, the explicit contentType
136: * will be used for all of them.
137: */
138: public static final String STREAM_CONTENTTYPE = "stream.contentType";
139:
140: /** 'true' if the header should include the handler name */
141: public static final String HEADER_ECHO_HANDLER = "echoHandler";
142:
143: /** include the parameters in the header **/
144: public static final String HEADER_ECHO_PARAMS = "echoParams";
145:
146: /** valid values for: <code>echoParams</code> */
147: public enum EchoParamStyle {
148: EXPLICIT, ALL, NONE;
149:
150: public static EchoParamStyle get(String v) {
151: if (v != null) {
152: v = v.toUpperCase();
153: if (v.equals("EXPLICIT")) {
154: return EXPLICIT;
155: }
156: if (v.equals("ALL")) {
157: return ALL;
158: }
159: if (v.equals("NONE")) { // the same as nothing...
160: return NONE;
161: }
162: }
163: return null;
164: }
165: };
166:
167: /** returns the String value of a param, or null if not set */
168: public abstract String get(String param);
169:
170: /** returns an array of the String values of a param, or null if none */
171: public abstract String[] getParams(String param);
172:
173: /** returns an Iterator over the parameter names */
174: public abstract Iterator<String> getParameterNamesIterator();
175:
176: /** returns the value of the param, or def if not set */
177: public String get(String param, String def) {
178: String val = get(param);
179: return val == null ? def : val;
180: }
181:
182: /** returns a RequiredSolrParams wrapping this */
183: public RequiredSolrParams required() {
184: // TODO? should we want to stash a reference?
185: return new RequiredSolrParams(this );
186: }
187:
188: protected String fpname(String field, String param) {
189: return "f." + field + '.' + param;
190: }
191:
192: /** returns the String value of the field parameter, "f.field.param", or
193: * the value for "param" if that is not set.
194: */
195: public String getFieldParam(String field, String param) {
196: String val = get(fpname(field, param));
197: return val != null ? val : get(param);
198: }
199:
200: /** returns the String value of the field parameter, "f.field.param", or
201: * the value for "param" if that is not set. If that is not set, def
202: */
203: public String getFieldParam(String field, String param, String def) {
204: String val = get(fpname(field, param));
205: return val != null ? val : get(param, def);
206: }
207:
208: /** returns the String values of the field parameter, "f.field.param", or
209: * the values for "param" if that is not set.
210: */
211: public String[] getFieldParams(String field, String param) {
212: String[] val = getParams(fpname(field, param));
213: return val != null ? val : getParams(param);
214: }
215:
216: /** Returns the Boolean value of the param, or null if not set */
217: public Boolean getBool(String param) {
218: String val = get(param);
219: return val == null ? null : parseBool(val);
220: }
221:
222: /** Returns the boolean value of the param, or def if not set */
223: public boolean getBool(String param, boolean def) {
224: String val = get(param);
225: return val == null ? def : parseBool(val);
226: }
227:
228: /** Returns the Boolean value of the field param,
229: or the value for param, or null if neither is set. */
230: public Boolean getFieldBool(String field, String param) {
231: String val = getFieldParam(field, param);
232: return val == null ? null : parseBool(val);
233: }
234:
235: /** Returns the boolean value of the field param,
236: or the value for param, or def if neither is set. */
237: public boolean getFieldBool(String field, String param, boolean def) {
238: String val = getFieldParam(field, param);
239: return val == null ? def : parseBool(val);
240: }
241:
242: /** Returns the Integer value of the param, or null if not set */
243: public Integer getInt(String param) {
244: String val = get(param);
245: try {
246: return val == null ? null : Integer.valueOf(val);
247: } catch (Exception ex) {
248: throw new SolrException(
249: SolrException.ErrorCode.BAD_REQUEST, ex
250: .getMessage(), ex);
251: }
252: }
253:
254: /** Returns the int value of the param, or def if not set */
255: public int getInt(String param, int def) {
256: String val = get(param);
257: try {
258: return val == null ? def : Integer.parseInt(val);
259: } catch (Exception ex) {
260: throw new SolrException(
261: SolrException.ErrorCode.BAD_REQUEST, ex
262: .getMessage(), ex);
263: }
264: }
265:
266: /** Returns the int value of the field param,
267: or the value for param, or def if neither is set. */
268: public Integer getFieldInt(String field, String param) {
269: String val = getFieldParam(field, param);
270: try {
271: return val == null ? null : Integer.valueOf(val);
272: } catch (Exception ex) {
273: throw new SolrException(
274: SolrException.ErrorCode.BAD_REQUEST, ex
275: .getMessage(), ex);
276: }
277: }
278:
279: /** Returns the int value of the field param,
280: or the value for param, or def if neither is set. */
281: public int getFieldInt(String field, String param, int def) {
282: String val = getFieldParam(field, param);
283: try {
284: return val == null ? def : Integer.parseInt(val);
285: } catch (Exception ex) {
286: throw new SolrException(
287: SolrException.ErrorCode.BAD_REQUEST, ex
288: .getMessage(), ex);
289: }
290: }
291:
292: /** Returns the Float value of the param, or null if not set */
293: public Float getFloat(String param) {
294: String val = get(param);
295: try {
296: return val == null ? null : Float.valueOf(val);
297: } catch (Exception ex) {
298: throw new SolrException(
299: SolrException.ErrorCode.BAD_REQUEST, ex
300: .getMessage(), ex);
301: }
302: }
303:
304: /** Returns the float value of the param, or def if not set */
305: public float getFloat(String param, float def) {
306: String val = get(param);
307: try {
308: return val == null ? def : Float.parseFloat(val);
309: } catch (Exception ex) {
310: throw new SolrException(
311: SolrException.ErrorCode.BAD_REQUEST, ex
312: .getMessage(), ex);
313: }
314: }
315:
316: /** Returns the float value of the field param. */
317: public Float getFieldFloat(String field, String param) {
318: String val = getFieldParam(field, param);
319: try {
320: return val == null ? null : Float.valueOf(val);
321: } catch (Exception ex) {
322: throw new SolrException(
323: SolrException.ErrorCode.BAD_REQUEST, ex
324: .getMessage(), ex);
325: }
326: }
327:
328: /** Returns the float value of the field param,
329: or the value for param, or def if neither is set. */
330: public float getFieldFloat(String field, String param, float def) {
331: String val = getFieldParam(field, param);
332: try {
333: return val == null ? def : Float.parseFloat(val);
334: } catch (Exception ex) {
335: throw new SolrException(
336: SolrException.ErrorCode.BAD_REQUEST, ex
337: .getMessage(), ex);
338: }
339: }
340:
341: /** how to transform a String into a boolean... more flexible than
342: * Boolean.parseBoolean() to enable easier integration with html forms.
343: */
344: protected boolean parseBool(String s) {
345: if (s != null) {
346: if (s.startsWith("true") || s.startsWith("on")
347: || s.startsWith("yes")) {
348: return true;
349: }
350: if (s.startsWith("false") || s.startsWith("off")
351: || s.equals("no")) {
352: return false;
353: }
354: }
355: throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
356: "invalid boolean value: " + s);
357: }
358:
359: /** Create a Map<String,String> from a NamedList given no keys are repeated */
360: public static Map<String, String> toMap(NamedList params) {
361: HashMap<String, String> map = new HashMap<String, String>();
362: for (int i = 0; i < params.size(); i++) {
363: map.put(params.getName(i), params.getVal(i).toString());
364: }
365: return map;
366: }
367:
368: /** Create a Map<String,String[]> from a NamedList */
369: public static Map<String, String[]> toMultiMap(NamedList params) {
370: HashMap<String, String[]> map = new HashMap<String, String[]>();
371: for (int i = 0; i < params.size(); i++) {
372: String name = params.getName(i);
373: String val = params.getVal(i).toString();
374: MultiMapSolrParams.addParam(name, val, map);
375: }
376: return map;
377: }
378:
379: /** Create SolrParams from NamedList. */
380: public static SolrParams toSolrParams(NamedList params) {
381: // if no keys are repeated use the faster MapSolrParams
382: HashMap<String, String> map = new HashMap<String, String>();
383: for (int i = 0; i < params.size(); i++) {
384: String prev = map.put(params.getName(i), params.getVal(i)
385: .toString());
386: if (prev != null)
387: return new MultiMapSolrParams(toMultiMap(params));
388: }
389: return new MapSolrParams(map);
390: }
391:
392: /** Convert this to a NamedList */
393: public NamedList<Object> toNamedList() {
394: final SimpleOrderedMap<Object> result = new SimpleOrderedMap<Object>();
395:
396: for (Iterator<String> it = getParameterNamesIterator(); it
397: .hasNext();) {
398: final String name = it.next();
399: final String[] values = getParams(name);
400: if (values.length == 1) {
401: result.add(name, values[0]);
402: } else {
403: // currently no reason not to use the same array
404: result.add(name, values);
405: }
406: }
407: return result;
408: }
409: }
|