source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2FieldSearch.java@ 24898

Last change on this file since 24898 was 24898, checked in by sjm84, 12 years ago

Raw search should not be on my default

  • Property svn:keywords set to Author Date Id Revision
File size: 26.0 KB
Line 
1/*
2 * AbstractGS2FieldSearch.java
3 * Copyright (C) 2006 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18package org.greenstone.gsdl3.service;
19
20// Greenstone classes
21import org.greenstone.gsdl3.util.*;
22
23// XML classes
24import org.w3c.dom.Document;
25import org.w3c.dom.Element;
26import org.w3c.dom.NodeList;
27
28// java classes
29import java.util.Iterator;
30import java.util.Set;
31import java.util.HashMap;
32import java.util.Map;
33import java.util.ArrayList;
34import java.util.Vector;
35import java.io.File;
36
37import org.apache.log4j.*;
38
39abstract public class AbstractGS2FieldSearch extends AbstractGS2TextSearch
40{
41 // extra services offered by mgpp collections
42 protected static final String FIELD_QUERY_SERVICE = "FieldQuery";
43 protected static final String ADVANCED_FIELD_QUERY_SERVICE = "AdvancedFieldQuery";
44 protected static final String RAW_QUERY_SERVICE = "RawQuery";
45
46 // extra parameters used
47 protected static final String LEVEL_PARAM = "level";
48 protected static final String RANK_PARAM = "sortBy";
49 protected static final String RANK_PARAM_RANK = "1";
50 protected static final String RANK_PARAM_NONE = "0";
51 protected static final String SIMPLE_FIELD_PARAM = "simpleField";
52 protected static final String ADVANCED_FIELD_PARAM = "complexField";
53
54 protected static final String RAW_PARAM = "rawquery";
55
56 // more params for field query
57 protected static final String FIELD_QUERY_PARAM = "fqv";
58 protected static final String FIELD_STEM_PARAM = "fqs";
59 protected static final String FIELD_CASE_PARAM = "fqc";
60 protected static final String FIELD_ACCENT_PARAM = "fqa";
61 protected static final String FIELD_FIELD_PARAM = "fqf";
62 protected static final String FIELD_COMBINE_PARAM = "fqk";
63 protected static final String FIELD_COMBINE_PARAM_AND = "0";
64 protected static final String FIELD_COMBINE_PARAM_OR = "1";
65 protected static final String FIELD_COMBINE_PARAM_NOT = "2";
66
67 // some stuff for config files
68 protected static final String SEARCH_TYPE_ELEM = "searchType";
69 protected static final String SEARCH_TYPE_PLAIN = "plain";
70 protected static final String SEARCH_TYPE_SIMPLE_FORM = "simpleform";
71 protected static final String SEARCH_TYPE_ADVANCED_FORM = "advancedform";
72 protected static final String SEARCH_TYPE_RAW = "raw";
73
74 protected static final String DEFAULT_LEVEL_ELEM = "defaultLevel";
75 protected static final String DEFAULT_DB_LEVEL_ELEM = "defaultDBLevel";
76 protected static final String LEVEL_ELEM = "level";
77 protected static final String FIELD_ATT = "field";
78
79 protected static final int TEXT_QUERY = 0;
80 protected static final int SIMPLE_QUERY = 1;
81 protected static final int ADVANCED_QUERY = 2;
82 protected static final int RAW_QUERY = 3;
83
84 protected String AND_OPERATOR = "&";
85 protected String OR_OPERATOR = "|";
86 protected String NOT_OPERATOR = "!";
87
88 // the default level for searching
89 protected String default_level = null;
90 // default level for collection db
91 protected String default_db_level = null;
92 // which search services will we offer??
93 protected boolean plain_search = false;
94 protected boolean simple_form_search = false;
95 protected boolean advanced_form_search = false;
96 protected boolean raw_search = false;
97
98 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.AbstractGS2FieldSearch.class.getName());
99
100 /** constructor */
101 public AbstractGS2FieldSearch()
102 {
103 }
104
105 public void cleanUp()
106 {
107 super.cleanUp();
108 }
109
110 /** configure this service */
111 public boolean configure(Element info, Element extra_info)
112 {
113 if (!super.configure(info, extra_info))
114 {
115 return false;
116 }
117
118 // Get the default level out of <defaultLevel> (buildConfig.xml)
119 Element def = (Element) GSXML.getChildByTagName(info, DEFAULT_LEVEL_ELEM);
120 if (def != null)
121 {
122 this.default_level = def.getAttribute(GSXML.SHORTNAME_ATT);
123 }
124 if (this.default_level == null || this.default_level.equals(""))
125 {
126 logger.error("default level not specified!, assuming Doc");
127 this.default_level = "Doc";
128 }
129
130 // Get the default DB level
131 def = (Element) GSXML.getChildByTagName(info, DEFAULT_DB_LEVEL_ELEM);
132 if (def != null)
133 {
134 this.default_db_level = def.getAttribute(GSXML.SHORTNAME_ATT);
135 }
136 if (this.default_db_level == null || this.default_db_level.equals(""))
137 {
138 logger.error("default database level (defaultDBLevel) not specified!, assuming Sec");
139 this.default_db_level = "Sec";
140 }
141
142 // get stuff from from extra info (which is collectionConfig.xml)
143 if (extra_info != null)
144 {
145
146 // the search element
147 Element config_search = (Element) GSXML.getChildByTagName(extra_info, GSXML.SEARCH_ELEM);
148
149 NodeList search_types = config_search.getElementsByTagName(SEARCH_TYPE_ELEM);
150 if (search_types == null)
151 {
152 // none specified, assume plain only
153 this.plain_search = true;
154 }
155 else
156 {
157 for (int i = 0; i < search_types.getLength(); i++)
158 {
159 Element t = (Element) search_types.item(i);
160 String type_name = t.getAttribute(GSXML.NAME_ATT);
161 if (type_name.equals(SEARCH_TYPE_PLAIN))
162 {
163 this.plain_search = true;
164 }
165 else if (type_name.equals(SEARCH_TYPE_SIMPLE_FORM))
166 {
167 this.simple_form_search = true;
168 }
169 else if (type_name.equals(SEARCH_TYPE_ADVANCED_FORM))
170 {
171 this.advanced_form_search = true;
172 }
173 else if (type_name.equals(SEARCH_TYPE_RAW))
174 {
175 this.raw_search = true;
176 }
177 }
178 }
179
180 // AbstractGS2TextSearch has set up the TextQuery service, but we may not want it
181 if (!this.plain_search)
182 {
183 // need to remove the TextQuery service
184 Element tq_service = GSXML.getNamedElement(short_service_info, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, QUERY_SERVICE);
185 short_service_info.removeChild(tq_service);
186
187 }
188
189 Document owner = info.getOwnerDocument();
190
191 NodeList levels = info.getElementsByTagName(GSXML.LEVEL_ELEM);
192
193 for (int i = 0; i < levels.getLength(); i++)
194 {
195 Element lev = (Element) levels.item(i);
196 String name = lev.getAttribute(GSXML.NAME_ATT);
197 Element node_extra = GSXML.getNamedElement(config_search, GSXML.LEVEL_ELEM, GSXML.NAME_ATT, name);
198 if (node_extra == null)
199 {
200 logger.error("haven't found extra info for level named " + name);
201 continue;
202 }
203
204 // get the display elements if any - displayName
205 NodeList display_names = node_extra.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
206 if (display_names != null)
207 {
208 for (int j = 0; j < display_names.getLength(); j++)
209 {
210 Element e = (Element) display_names.item(j);
211 lev.appendChild(owner.importNode(e, true));
212 }
213 }
214 } // for each level
215 }
216 else
217 {
218 // for soem reason we don't have the collectionConfig file. assume plain only
219 this.plain_search = true;
220 }
221
222 // the format info is the same for all services
223 Element format_info = (Element) format_info_map.get(QUERY_SERVICE);
224
225 // set up the extra services which are available for this collection
226 if (this.simple_form_search)
227 {
228 // set up short_service_info_ - for now just has id and type - name will be added in on the fly
229 Element fq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
230 fq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
231 fq_service.setAttribute(GSXML.NAME_ATT, FIELD_QUERY_SERVICE);
232 this.short_service_info.appendChild(fq_service);
233
234 if (format_info != null)
235 {
236 this.format_info_map.put(FIELD_QUERY_SERVICE, format_info);
237 }
238 }
239
240 if (this.advanced_form_search)
241 {
242 Element afq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
243 afq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
244 afq_service.setAttribute(GSXML.NAME_ATT, ADVANCED_FIELD_QUERY_SERVICE);
245 this.short_service_info.appendChild(afq_service);
246
247 if (format_info != null)
248 {
249 this.format_info_map.put(ADVANCED_FIELD_QUERY_SERVICE, format_info);
250 }
251 }
252
253 if (this.raw_search)
254 {
255 Element rq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
256 rq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
257 rq_service.setAttribute(GSXML.NAME_ATT, RAW_QUERY_SERVICE);
258 this.short_service_info.appendChild(rq_service);
259
260 if (format_info != null)
261 {
262 this.format_info_map.put(RAW_QUERY_SERVICE, format_info);
263 }
264 }
265
266 return true;
267 }
268
269 protected Element getServiceDescription(String service_id, String lang, String subset)
270 {
271 // should we check that the service is actually on offer? presumably we wont get asked for services that we haven't advertised previously.
272
273 if (!service_id.equals(FIELD_QUERY_SERVICE) && !service_id.equals(ADVANCED_FIELD_QUERY_SERVICE) && !service_id.equals(RAW_QUERY_SERVICE))
274 {
275 return super.getServiceDescription(service_id, lang, subset);
276 }
277
278 Element service = this.doc.createElement(GSXML.SERVICE_ELEM);
279 service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
280 service.setAttribute(GSXML.NAME_ATT, service_id);
281 if (subset == null || subset.equals(GSXML.DISPLAY_TEXT_ELEM + GSXML.LIST_MODIFIER))
282 {
283 service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, getTextString(service_id + ".name", lang)));
284 service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_SUBMIT, getTextString(service_id + ".submit", lang)));
285 service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getTextString(service_id + ".description", lang)));
286
287 }
288 if (subset == null || subset.equals(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER))
289 {
290 Element param_list = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
291 service.appendChild(param_list);
292 if (service_id.equals(FIELD_QUERY_SERVICE))
293 {
294
295 addCustomQueryParams(param_list, lang);
296 createParameter(MAXDOCS_PARAM, param_list, lang);
297 if (!default_index_subcollection.equals(""))
298 {
299 createParameter(INDEX_SUBCOLLECTION_PARAM, param_list, lang);
300 }
301 if (!default_index_language.equals(""))
302 {
303 createParameter(INDEX_LANGUAGE_PARAM, param_list, lang);
304 }
305 // create a multi param for the fields etc
306 // text box, field
307 Element multiparam = null;
308 Element param = null;
309 multiparam = GSXML.createParameterDescription(this.doc, SIMPLE_FIELD_PARAM, "", GSXML.PARAM_TYPE_MULTI, null, null, null);
310 multiparam.setAttribute("occurs", "4");
311 param_list.appendChild(multiparam);
312
313 // the components
314
315 createParameter(FIELD_QUERY_PARAM, multiparam, lang);
316 createParameter(FIELD_FIELD_PARAM, multiparam, lang);
317
318 }
319 else if (service_id.equals(ADVANCED_FIELD_QUERY_SERVICE))
320 {
321 createParameter(LEVEL_PARAM, param_list, lang);
322 createParameter(RANK_PARAM, param_list, lang);
323 createParameter(MAXDOCS_PARAM, param_list, lang);
324 if (!default_index_subcollection.equals(""))
325 {
326 createParameter(INDEX_SUBCOLLECTION_PARAM, param_list, lang);
327 }
328 if (!default_index_language.equals(""))
329 {
330 createParameter(INDEX_LANGUAGE_PARAM, param_list, lang);
331 }
332
333 // create a multi param for the fields etc
334 // text box, stem, case, field
335
336 Element multiparam = null;
337 Element param = null;
338
339 multiparam = GSXML.createParameterDescription(this.doc, ADVANCED_FIELD_PARAM, "", GSXML.PARAM_TYPE_MULTI, null, null, null);
340 multiparam.setAttribute("occurs", "4");
341 param_list.appendChild(multiparam);
342
343 createParameter(FIELD_COMBINE_PARAM, multiparam, lang);
344 createParameter(FIELD_QUERY_PARAM, multiparam, lang);
345 if (this.does_case)
346 {
347 createParameter(FIELD_CASE_PARAM, multiparam, lang);
348 }
349 if (this.does_stem)
350 {
351 createParameter(FIELD_STEM_PARAM, multiparam, lang);
352 }
353 if (this.does_accent)
354 {
355 createParameter(FIELD_ACCENT_PARAM, multiparam, lang);
356 }
357 createParameter(FIELD_FIELD_PARAM, multiparam, lang);
358
359 }
360 else if (service_id.equals(RAW_QUERY_SERVICE))
361 {
362 if (does_chunking)
363 {
364 createParameter(MAXDOCS_PARAM, param_list, lang);
365 }
366 if (does_paging)
367 {
368 createParameter(HITS_PER_PAGE_PARAM, param_list, lang);
369 createParameter(START_PAGE_PARAM, param_list, lang);
370 }
371 createParameter(RAW_PARAM, param_list, lang);
372 service.appendChild(param_list);
373 }
374 }
375 return service;
376
377 }
378
379 /** add in the level params to TextQuery */
380 protected void addCustomQueryParams(Element param_list, String lang)
381 {
382 createParameter(LEVEL_PARAM, param_list, lang);
383 super.addCustomQueryParams(param_list, lang);
384 }
385
386 /** create a param and add to the list */
387 protected void createParameter(String name, Element param_list, String lang)
388 {
389 Element param = null;
390 if (name.equals(LEVEL_PARAM))
391 {
392 ArrayList level_ids = new ArrayList();
393 ArrayList level_names = new ArrayList();
394 getLevelData(level_ids, level_names, lang);
395 if (level_ids.size() > 1)
396 {
397 // the first one is the default
398 //param = GSXML.createParameterDescription2(this.doc, LEVEL_PARAM, getTextString("param."+LEVEL_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, (String)level_ids.get(0), level_ids, level_names);
399 param = GSXML.createParameterDescription2(this.doc, LEVEL_PARAM, getTextString("param." + LEVEL_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, this.default_level, level_ids, level_names);
400 }
401 else
402 {
403 // we need to set the level, but hidden, in case there is an invalid level saved
404 //param = GSXML.createParameterDescription(this.doc, LEVEL_PARAM, "", GSXML.PARAM_TYPE_INVISIBLE, (String)level_ids.get(0), null, null);
405 param = GSXML.createParameterDescription(this.doc, LEVEL_PARAM, "", GSXML.PARAM_TYPE_INVISIBLE, this.default_level, null, null);
406 }
407 }
408 else if (name.equals(RANK_PARAM))
409 {
410 String[] vals1 = { RANK_PARAM_RANK, RANK_PARAM_NONE };
411 String[] vals1_texts = { getTextString("param." + RANK_PARAM + "." + RANK_PARAM_RANK, lang), getTextString("param." + RANK_PARAM + "." + RANK_PARAM_NONE, lang) };
412
413 param = GSXML.createParameterDescription(this.doc, RANK_PARAM, getTextString("param." + RANK_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, RANK_PARAM_RANK, vals1, vals1_texts);
414
415 }
416 else if (name.equals(FIELD_QUERY_PARAM))
417 {
418 param = GSXML.createParameterDescription(this.doc, FIELD_QUERY_PARAM, getTextString("param." + FIELD_QUERY_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
419
420 }
421 else if (name.equals(FIELD_CASE_PARAM) || name.equals(FIELD_STEM_PARAM) || name.equals(FIELD_ACCENT_PARAM))
422 {
423 String[] bool_ops = { "0", "1" };
424 String[] bool_texts = { getTextString("param.boolean.off", lang, "AbstractTextSearch"), getTextString("param.boolean.on", lang, "AbstractTextSearch") };
425 param = GSXML.createParameterDescription(this.doc, name, getTextString("param." + name, lang), GSXML.PARAM_TYPE_BOOLEAN, BOOLEAN_PARAM_ON, bool_ops, bool_texts);
426
427 }
428 else if (name.equals(FIELD_FIELD_PARAM))
429 {
430 ArrayList fields = new ArrayList();
431 ArrayList field_names = new ArrayList();
432 getIndexData(fields, field_names, lang);
433 // the field list - read from config file
434
435 // Fix for http://trac.greenstone.org/ticket/245 "java crash, index out of bounds"
436 // org.greenstone.gsdl3.service.AbstractGS2FieldSearch.createParameter(AbstractGS2FieldSearch.java:362)
437 // Changed from:
438 // param = GSXML.createParameterDescription2(this.doc, name, getTextString("param."+name, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, (String)fields.get(0), fields, field_names );
439 String default_value = (fields.size() > 0) ? (String) fields.get(0) : null;
440 // don't want to access element 0 if fields.size()==0, and
441 // GSXML.createParameterDescription2 checks for default_value==null condition
442 param = GSXML.createParameterDescription2(this.doc, name, getTextString("param." + name, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, default_value, fields, field_names);
443
444 }
445 else if (name.equals(FIELD_COMBINE_PARAM))
446 {
447
448 String[] vals = { FIELD_COMBINE_PARAM_AND, FIELD_COMBINE_PARAM_OR, FIELD_COMBINE_PARAM_NOT };
449 String[] val_texts = { getTextString("param." + FIELD_COMBINE_PARAM + "." + FIELD_COMBINE_PARAM_AND, lang), getTextString("param." + FIELD_COMBINE_PARAM + "." + FIELD_COMBINE_PARAM_OR, lang), getTextString("param." + FIELD_COMBINE_PARAM + "." + FIELD_COMBINE_PARAM_NOT, lang) };
450
451 param = GSXML.createParameterDescription(this.doc, FIELD_COMBINE_PARAM, "", GSXML.PARAM_TYPE_ENUM_SINGLE, FIELD_COMBINE_PARAM_AND, vals, val_texts);
452 param.setAttribute(GSXML.PARAM_IGNORE_POS_ATT, "0");
453 }
454
455 if (param != null)
456 {
457 param_list.appendChild(param);
458 }
459 else
460 {
461 super.createParameter(name, param_list, lang);
462 }
463 }
464
465 // should cache some of this
466 protected void getLevelData(ArrayList level_ids, ArrayList level_names, String lang)
467 {
468 Element level_list = (Element) GSXML.getChildByTagName(this.config_info, LEVEL_ELEM + GSXML.LIST_MODIFIER);
469 NodeList levels = level_list.getElementsByTagName(LEVEL_ELEM);
470 for (int i = 0; i < levels.getLength(); i++)
471 {
472 Element level = (Element) levels.item(i);
473 String shortname = level.getAttribute(GSXML.SHORTNAME_ATT);
474 if (shortname.equals(""))
475 {
476 continue;
477 }
478 level_ids.add(shortname);
479 String display_name = GSXML.getDisplayText(level, GSXML.DISPLAY_TEXT_NAME, lang, "en");
480 if (display_name.equals(""))
481 {
482 // we'll use the name, and the dictionary
483 display_name = level.getAttribute(GSXML.NAME_ATT);
484 if (display_name.equals(""))
485 {
486 display_name = shortname;
487 }
488 else
489 {
490 display_name = getTextString("level." + display_name, lang);
491 }
492 }
493 level_names.add(display_name);
494 }
495 }
496
497 // the following three functions are needed so the base class can
498 // call the process+SERVICE_NAME methods
499 /** process a text query */
500 protected Element processTextQuery(Element request)
501 {
502 return processAnyQuery(request, TEXT_QUERY);
503 }
504
505 /** process a field query */
506 protected Element processFieldQuery(Element request)
507 {
508 return processAnyQuery(request, SIMPLE_QUERY);
509 }
510
511 /** process an advanced field query */
512 protected Element processAdvancedFieldQuery(Element request)
513 {
514 return processAnyQuery(request, ADVANCED_QUERY);
515 }
516
517 protected Element processRawQuery(Element request)
518 {
519 return processAnyQuery(request, RAW_QUERY);
520 }
521
522 /** process a query */
523 protected Element processAnyQuery(Element request, int query_type)
524 {
525 String service_name = null;
526 String empty_query_test_param = null;
527 // set up the type specific bits
528 switch (query_type)
529 {
530 case TEXT_QUERY:
531 service_name = QUERY_SERVICE;
532 empty_query_test_param = QUERY_PARAM;
533 break;
534 case SIMPLE_QUERY:
535 service_name = FIELD_QUERY_SERVICE;
536 empty_query_test_param = FIELD_QUERY_PARAM;
537 break;
538 case ADVANCED_QUERY:
539 service_name = ADVANCED_FIELD_QUERY_SERVICE;
540 empty_query_test_param = FIELD_QUERY_PARAM;
541 break;
542 case RAW_QUERY:
543 service_name = RAW_QUERY_SERVICE;
544 empty_query_test_param = RAW_PARAM;
545 break;
546 default:
547 // should never get here
548 logger.error("wrong query type!!");
549 return null;
550 }
551
552 // Create a new (empty) result message
553 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
554 result.setAttribute(GSXML.FROM_ATT, service_name);
555 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
556
557 // Get the parameters of the request
558 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
559 if (param_list == null)
560 {
561 logger.error("TextQuery request had no paramList.");
562 return result; // Return the empty result
563 }
564
565 // Process the request parameters
566 HashMap params = GSXML.extractParams(param_list, false);
567
568 // Make sure a query has been specified
569 String query = (String) params.get(empty_query_test_param);
570 if (query == null || query.equals(""))
571 {
572 return result; // Return the empty result
573 }
574
575 // If a field hasn't been specified, use the default - for textQuery
576 String field = (String) params.get(INDEX_PARAM);
577 if (field == null)
578 {
579 field = default_index;
580 }
581
582 // set up the appropriate query system
583 if (!setUpQueryer(params))
584 {
585 return result;
586 }
587
588 // if field search, create the query string
589 switch (query_type)
590 {
591 case TEXT_QUERY:
592 query = addFieldInfo(query, field);
593 break;
594 case SIMPLE_QUERY:
595 query = parseFieldQueryParams(params);
596 break;
597 case ADVANCED_QUERY:
598 query = parseAdvancedFieldQueryParams(params);
599 break;
600 }
601
602 // run the query
603 Object query_result = runQuery(query);
604
605 // build up the response
606
607 // Create a metadata list to store information about the query results
608 // should we be using metadataList? or something else?
609 Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
610 result.appendChild(metadata_list);
611
612 // Add a metadata element specifying the number of matching documents
613 long totalDocs = numDocsMatched(query_result);
614
615 GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", "" + totalDocs);
616
617 // Create a document list to store the matching documents, and add them
618 String[] docs = getDocIDs(query_result);
619 String[] doc_ranks = getDocRanks(query_result);
620
621 // add a metadata item to specify docs returned
622 int docs_returned = docs.length;
623 if (does_paging)
624 {
625 String maxdocs_str = (String) params.get(MAXDOCS_PARAM);
626 if (maxdocs_str != null)
627 {
628 int maxdocs = Integer.parseInt(maxdocs_str);
629 docs_returned = (maxdocs < (int) totalDocs ? maxdocs : (int) totalDocs);
630 }
631 }
632 GSXML.addMetadata(this.doc, metadata_list, "numDocsReturned", "" + docs_returned);
633
634 // add a metadata item to specify what actual query was done - eg if stuff was stripped out etc. and then we can use the query later, cos we don't know which parameter was the query
635 GSXML.addMetadata(this.doc, metadata_list, "query", query);
636 if (docs.length > 0)
637 {
638 Element document_list = this.doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
639 result.appendChild(document_list);
640 for (int d = 0; d < docs.length; d++)
641 {
642 String doc_id = internalNum2OID(docs[d]);
643 Element doc_node = createDocNode(doc_id, doc_ranks[d]);
644 document_list.appendChild(doc_node);
645 }
646 }
647
648 // Create a term list to store the term information, and add it
649 Element term_list = this.doc.createElement(GSXML.TERM_ELEM + GSXML.LIST_MODIFIER);
650 result.appendChild(term_list);
651 addTermInfo(term_list, params, query_result);
652
653 return result;
654
655 }
656
657 /** methods to handle actually doing the query */
658 /** do any initialisation of the query object */
659 abstract protected boolean setUpQueryer(HashMap params);
660
661 /** do the query */
662 abstract protected Object runQuery(String query);
663
664 /** get the total number of docs that match */
665 abstract protected long numDocsMatched(Object query_result);
666
667 /** get the list of doc ids */
668 abstract protected String[] getDocIDs(Object query_result);
669
670 /** get the list of doc ranks */
671 abstract protected String[] getDocRanks(Object query_result);
672
673 /** add in term info if available */
674 abstract protected boolean addTermInfo(Element term_list, HashMap params, Object query_result);
675
676 /**
677 * combines all the field params into a single query - for simple field
678 * query
679 */
680 /** We assume the combination (AND/OR) is done by the match param */
681 protected String parseFieldQueryParams(HashMap params)
682 {
683
684 StringBuffer final_query = new StringBuffer(256);
685 String text_line = (String) params.get(FIELD_QUERY_PARAM);
686 String[] texts = text_line.split(",", -1);
687 String field_line = (String) params.get(FIELD_FIELD_PARAM);
688 String[] fields = field_line.split(",", -1);
689
690 for (int i = 0; i < texts.length; i++)
691 {
692 String q = texts[i].trim();
693 if (!q.equals(""))
694 {
695 final_query.append(" " + addFieldInfo(q, fields[i]));
696 }
697 }
698
699 return final_query.toString();
700 }
701
702 abstract protected String addFieldInfo(String query, String field);
703
704 /**
705 * combines all the field params into a single query - for advanced field
706 * query
707 */
708 protected String parseAdvancedFieldQueryParams(HashMap params)
709 {
710
711 StringBuffer final_query = new StringBuffer(256);
712 String text_line = (String) params.get(FIELD_QUERY_PARAM);
713 String[] texts = text_line.split(",", -1);
714 String field_line = (String) params.get(FIELD_FIELD_PARAM);
715 String[] fields = field_line.split(",", -1);
716 String[] cases = null;
717 String[] stems = null;
718 String[] accents = null;
719 if (does_case)
720 {
721 String case_line = (String) params.get(FIELD_CASE_PARAM);
722 if (case_line != null)
723 cases = case_line.split(",", -1);
724 }
725 if (does_stem)
726 {
727 String stem_line = (String) params.get(FIELD_STEM_PARAM);
728 if (stem_line != null)
729 stems = stem_line.split(",", -1);
730 }
731 if (does_accent)
732 {
733 String accent_line = (String) params.get(FIELD_ACCENT_PARAM);
734 if (accent_line != null)
735 accents = accent_line.split(",", -1);
736 }
737 String combine_line = (String) params.get(FIELD_COMBINE_PARAM);
738 String[] combines = combine_line.split(",", -1);
739 String combine = "";
740 for (int i = 0; i < texts.length; i++)
741 {
742 if (i == 0)
743 {// assume first one is blank
744 combine = "";
745 }
746 else
747 {
748 String x = combines[i];
749 if (x.equals(FIELD_COMBINE_PARAM_AND))
750 {
751 combine = AND_OPERATOR;
752 }
753 else if (x.equals(FIELD_COMBINE_PARAM_OR))
754 {
755 combine = OR_OPERATOR;
756 }
757 else if (x.equals(FIELD_COMBINE_PARAM_NOT))
758 {
759 combine = NOT_OPERATOR;
760 }
761
762 }
763
764 String q = texts[i].trim();
765 boolean modified = false;
766 if (!q.equals(""))
767 {
768 String c = null;
769 String s = null;
770 String a = null;
771 if (does_case)
772 {
773 modified = true;
774 c = cases[i];
775 }
776 if (does_stem)
777 {
778 modified = true;
779 s = stems[i];
780 }
781 if (does_accent)
782 {
783 modified = true;
784 a = accents[i];
785 }
786 if (modified)
787 {
788 q = addStemOptions(q, s, c, a);
789 }
790 addQueryElem(final_query, q, fields[i], combine);
791 }
792 }
793 return final_query.toString();
794 }
795
796 abstract protected void addQueryElem(StringBuffer final_query, String query, String field, String combine);
797
798 abstract protected String addStemOptions(String query, String stem, String casef, String accent);
799
800}
Note: See TracBrowser for help on using the repository browser.