source: trunk/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Search.java@ 4862

Last change on this file since 4862 was 4862, checked in by kjdon, 21 years ago

addeda test for null info from the gdbm db, when creating the doc nodes for results

  • Property svn:keywords set to Author Date Id Revision
File size: 13.2 KB
Line 
1/*
2 * GS2Search.java
3 * Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.service;
20
21
22// Greenstone classes
23import org.greenstone.gdbm.*;
24import org.greenstone.gsdl3.util.*;
25
26// XML classes
27import org.w3c.dom.Element;
28import org.w3c.dom.Document;
29import org.w3c.dom.NodeList;
30
31
32/**
33 *
34 * @author <a href="mailto:[email protected]">Michael Dewsnip</a>
35 * @version $Revision: 4862 $
36 */
37
38public abstract class GS2Search
39 extends ServiceRack {
40
41 // the services on offer
42 // these strings must match what is found in the properties file
43 protected static final String TEXT_QUERY_SERVICE = "TextQuery";
44
45 // Parameters used
46 protected static final String INDEX_PARAM = "index";
47 protected static final String CASE_PARAM = "case";
48 protected static final String STEM_PARAM = "stem";
49 protected static final String MATCH_PARAM = "matchMode";
50 protected static final String MATCH_PARAM_ALL = "all";
51 protected static final String MATCH_PARAM_SOME = "some";
52 protected static final String MAXDOCS_PARAM = "maxDocs";
53 protected static final String BOOLEAN_PARAM_ON = "1";
54 protected static final String BOOLEAN_PARAM_OFF = "0";
55 protected static final String QUERY_PARAM = "query";
56
57 protected static final String EQUIV_TERM_ELEM = "equivTerm";
58
59 protected static final String STEM_ATT = "stem";
60 protected static final String NUM_DOCS_MATCH_ATT = "numDocsMatch";
61 protected static final String FREQ_ATT = "freq";
62
63 // Elements used in the config file that are specific to this class
64 protected static final String DEFAULT_INDEX_ELEM = "defaultIndex";
65 protected static final String DEFAULT_LEVEL_ELEM = "defaultLevel";
66 protected static final String INDEX_ELEM = "index";
67 protected static final String LEVEL_ELEM = "level";
68
69 protected GDBMWrapper gdbm_src_ = null;
70
71 protected Element config_info_ = null;
72
73 /** the default index */
74 protected String default_index_ = null;
75
76
77 /** constructor */
78 public GS2Search()
79 {
80 gdbm_src_ = new GDBMWrapper();
81 }
82
83
84 /** configure this service */
85 public boolean configure(Element info, Element extra_info)
86 {
87 System.out.println("Configuring GS2Search...");
88 addExtraQueryInfo(info, extra_info);
89 config_info_ = info;
90
91 // Get the default index out of <defaultIndex> (buildConfig.xml)
92 Element def = (Element) GSXML.getChildByTagName(info, DEFAULT_INDEX_ELEM);
93 if (def != null) {
94 default_index_ = def.getAttribute(GSXML.NAME_ATT);
95 }
96 if (default_index_ == null || default_index_.equals("")) {
97 System.err.println("Error: default index not specified!");
98 return false;
99 }
100
101 // these entries should reflect the build config file - some services may not be available depending on how the colleciton was built.
102 // set up short_service_info_ - for now just has name and type
103 Element tq_service = doc_.createElement(GSXML.SERVICE_ELEM);
104 tq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
105 tq_service.setAttribute(GSXML.NAME_ATT, TEXT_QUERY_SERVICE);
106 short_service_info_.appendChild(tq_service);
107
108 // set up service_info_map_ - for now, just has the same elements as above
109 // should have full details about each service incl params lists etc.
110 Element tq_service_full = (Element) tq_service.cloneNode(true);
111 Element param_list = doc_.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
112 createTextQueryParamList(param_list, false, null);
113 tq_service_full.appendChild(param_list);
114 service_info_map_.put(TEXT_QUERY_SERVICE, tq_service_full);
115
116 // Open GDBM database for querying
117 String gdbm_db_file = GSFile.GDBMDatabaseFile(site_home_, cluster_name_);
118 if (!gdbm_src_.openDatabase(gdbm_db_file, GDBMWrapper.READER)) {
119 System.err.println("Error: Could not open GDBM database!");
120 return false;
121 }
122
123 // add some format info to service map if there is any
124 Element format = (Element) GSXML.getChildByTagName(info, GSXML.FORMAT_ELEM);
125 if (format != null) {
126 format_info_map_.put(TEXT_QUERY_SERVICE, doc_.importNode(format, true));
127 }
128
129 return true;
130 }
131
132
133 protected boolean addExtraQueryInfo(Element info, Element extra_info){
134
135 if (extra_info == null) {
136 return false;
137 }
138
139 Document owner = info.getOwnerDocument();
140 // so far we have index specific display elements, and global format elements
141 NodeList indexes = info.getElementsByTagName(GSXML.INDEX_ELEM);
142 Element config_search = (Element)GSXML.getChildByTagName(extra_info, GSXML.SEARCH_ELEM);
143
144 for (int i=0; i<indexes.getLength();i++) {
145 Element ind = (Element)indexes.item(i);
146 String name = ind.getAttribute(GSXML.NAME_ATT);
147 Element node_extra = GSXML.getNamedElement(config_search,
148 GSXML.INDEX_ELEM,
149 GSXML.NAME_ATT,
150 name);
151 if (node_extra == null) {
152 System.err.println("GS2Search: haven't found extra info for index named "+name);
153 continue;
154 }
155
156 // get the display elements if any - displayName
157 NodeList display_names = node_extra.getElementsByTagName(GSXML.DISPLAYNAME_ELEM);
158 if (display_names !=null) {
159 Element display = owner.createElement(GSXML.DISPLAY_ELEM);
160 for (int j=0; j<display_names.getLength(); j++) {
161 Element e = (Element)display_names.item(j);
162
163 Element display_name = GSXML.createTextElement(owner, GSXML.DISPLAY_NAME_ELEM, GSXML.getNodeText(e));
164 display_name.setAttribute(GSXML.LANG_ATT, e.getAttribute(GSXML.LANG_ATT));
165 display.appendChild(display_name);
166 }
167 ind.appendChild(display);
168 }
169 } // for each index
170
171 // get the format element if any
172 Element format = (Element)GSXML.getChildByTagName(config_search,
173 GSXML.FORMAT_ELEM);
174 if (format!=null) { // append to info
175 info.appendChild(owner.importNode(format, true));
176 }
177 return true;
178
179
180 }
181/** creates a new param element and adds it to the param list */
182 protected void createParameter(String name, Element param_list,
183 boolean display, String lang)
184 {
185 Element param=null;
186
187 if (name.equals(INDEX_PARAM)) {
188 // the index info - read from config file
189 Element index_list = (Element)GSXML.getChildByTagName(config_info_, INDEX_ELEM+GSXML.LIST_MODIFIER);
190 NodeList indexes = index_list.getElementsByTagName(INDEX_ELEM);
191 int len = indexes.getLength();
192 // now add even if there is only one
193 String [] inds = new String[len];
194 String [] ind_names = new String[len];
195 for (int i=0; i<len; i++) {
196 inds[i] = ((Element)indexes.item(i)).getAttribute(GSXML.NAME_ATT);
197 if (display) {
198 Element disp = (Element)GSXML.getChildByTagName(indexes.item(i), GSXML.DISPLAY_ELEM);
199 ind_names[i] = GSXML.getDisplayText(disp, GSXML.DISPLAY_NAME_ELEM, lang, "en");
200 }
201 }
202 if (display) {
203 param = GSXML.createParameterDisplay(doc_, INDEX_PARAM, getTextString("param."+INDEX_PARAM, lang), inds, ind_names);
204 } else {
205 param = GSXML.createParameterDescription(doc_, INDEX_PARAM, GSXML.PARAM_TYPE_ENUM_SINGLE, default_index_, inds);
206 }
207 } else if (name.equals(CASE_PARAM)) {
208 if (display) {
209 String[] bool_ops = {"0", "1"};
210 String[] bool_texts = {getTextString("param.boolean.off", lang),getTextString("param.boolean.on", lang)};
211 param = GSXML.createParameterDisplay(doc_, CASE_PARAM, getTextString("param."+CASE_PARAM, lang), bool_ops, bool_texts);
212 } else {
213 param = GSXML.createParameterDescription(doc_, CASE_PARAM, GSXML.PARAM_TYPE_BOOLEAN, BOOLEAN_PARAM_ON, null);
214 }
215 }
216 else if (name.equals(STEM_PARAM)) {
217 if (display) {
218 String[] bool_ops = {"0", "1"};
219 String[] bool_texts = {getTextString("param.boolean.off", lang),getTextString("param.boolean.on", lang)};
220 param = GSXML.createParameterDisplay(doc_, STEM_PARAM, getTextString("param."+STEM_PARAM, lang), bool_ops, bool_texts);
221 } else {
222 param = GSXML.createParameterDescription(doc_, STEM_PARAM, GSXML.PARAM_TYPE_BOOLEAN, BOOLEAN_PARAM_ON, null);
223 }
224 }
225 else if (name.equals(MATCH_PARAM)) {
226 String[] vals = {MATCH_PARAM_ALL, MATCH_PARAM_SOME};
227 if (display) {
228 String[] val_texts = {getTextString("param."+MATCH_PARAM+"."+MATCH_PARAM_ALL, lang),getTextString("param."+MATCH_PARAM+"."+MATCH_PARAM_SOME, lang)};
229
230 param = GSXML.createParameterDisplay(doc_, MATCH_PARAM, getTextString("param."+MATCH_PARAM, lang), vals, val_texts);
231 } else {
232 param = GSXML.createParameterDescription(doc_, MATCH_PARAM, GSXML.PARAM_TYPE_ENUM_SINGLE, MATCH_PARAM_ALL, vals);
233 }
234 }
235 else if (name.equals(MAXDOCS_PARAM)) {
236 if (display) {
237 param = GSXML.createParameterDisplay(doc_, MAXDOCS_PARAM, getTextString("param."+MAXDOCS_PARAM, lang), null, null);
238 } else {
239 param = GSXML.createParameterDescription(doc_, MAXDOCS_PARAM, GSXML.PARAM_TYPE_INTEGER, "10", null);
240 }
241 }
242 else if (name.equals(QUERY_PARAM)) {
243 if (display) {
244 param = GSXML.createParameterDisplay(doc_, QUERY_PARAM, getTextString("param."+QUERY_PARAM, lang), null, null);
245 } else {
246 param = GSXML.createParameterDescription(doc_, QUERY_PARAM, GSXML.PARAM_TYPE_STRING, null, null);
247 }
248 }
249
250 // add the param to the list
251 if (param != null) {
252 param_list.appendChild(param);
253 }
254 }
255
256
257 /** this creates all the params and appends them to param_list.
258 * if display=true it creates the text strings version
259 * otherwise it creates the description version
260 */
261 protected abstract boolean createTextQueryParamList(Element param_list,
262 boolean display,
263 String lang);
264
265 /** creates a display element containing all the text strings needed to display
266 the service page, in the language specified */
267 protected Element createServiceDisplay(String service, String lang)
268 {
269 // Create a service display for the basic text query service
270 Element display = doc_.createElement(GSXML.DISPLAY_ELEM);
271 display.appendChild(GSXML.createTextElement(doc_, GSXML.DISPLAY_NAME_ELEM, getTextString(service+".name", lang)));
272 display.appendChild(GSXML.createTextElement(doc_, GSXML.DISPLAY_SUBMIT_ELEM, getTextString(service+".submit", lang)));
273
274 // now need to add in the params
275 if (service.equals(TEXT_QUERY_SERVICE)) {
276 createTextQueryParamList(display, true, lang);
277 }
278
279 return display;
280 }
281
282
283 /** Creates a new documentNode element containing ID, node type
284 * and docType*/
285 protected Element createDocumentNodeElement(String node_id)
286 {
287 Element doc_node = doc_.createElement(GSXML.DOC_NODE_ELEM);
288 doc_node.setAttribute(GSXML.NODE_ID_ATT, node_id);
289
290 String top_id = OID.getTop(node_id);
291 boolean is_top = (top_id.equals(node_id) ? true : false);
292
293 DBInfo info = gdbm_src_.getInfo(node_id);
294 if (info == null) { // make it up - cant query the gdbm db
295 if (is_top) {
296 doc_node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_ROOT);
297 } else {
298 doc_node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_INTERIOR);
299 }
300 doc_node.setAttribute(GSXML.DOC_TYPE_ATT, "simple");
301 return doc_node;
302 }
303 String children = info.getInfo("contains");
304 boolean is_leaf = (children.equals("") ? true : false);
305
306 // set teh node type att
307 if (is_top) {
308 doc_node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_ROOT);
309 } else if (is_leaf) {
310 doc_node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_LEAF);
311 } else {
312 doc_node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_INTERIOR);
313 }
314
315 // set teh doc type att
316 if (is_top && is_leaf) { // a single section document
317 doc_node.setAttribute(GSXML.DOC_TYPE_ATT, "simple");
318 return doc_node;
319 }
320
321 if (!is_top) { // we need to look at the top info
322 info = gdbm_src_.getInfo(top_id);
323 }
324
325 String childtype = info.getInfo("childtype");
326 if (childtype.equals("Paged")) {
327 doc_node.setAttribute(GSXML.DOC_TYPE_ATT, "paged");
328 } else {
329 doc_node.setAttribute(GSXML.DOC_TYPE_ATT, "hierarchy");
330 }
331 return doc_node;
332 }
333
334 /** returns the document type of a node - if the node is a subnode, it returns teh type of teh top document node. for now, only does paged and hierarchical, but eventually will have more types */
335 protected String getDocType(String node_id) {
336
337 String doc_id = OID.getTop(node_id);
338 DBInfo info = gdbm_src_.getInfo(doc_id);
339 String child_type = info.getInfo("childtype");
340 if (child_type.equals("Paged")) {
341 return "paged";
342 }
343 return "hierarchy";
344
345 }
346
347 /** Returns true if the OID specifies a leaf node, false otherwise
348 Note: this makes a request to the GDBM database so it may not be cheap */
349 protected boolean isLeafNode(String oid)
350 {
351 DBInfo info = gdbm_src_.getInfo(oid);
352 String children = info.getInfo("contains");
353 return (children.equals(""));
354 }
355
356
357 /** Process a text query - implemented by concrete subclasses */
358 protected abstract Element processTextQuery(Element request);
359}
Note: See TracBrowser for help on using the repository browser.