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

Last change on this file since 21655 was 21655, checked in by kjdon, 14 years ago

search types. code was looking for searchtype list in buildconfig, but collconfig had format element. now have searchType elements in search element of collconfig. need to make GLI write that.

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