source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/QueryAction.java@ 30476

Last change on this file since 30476 was 30476, checked in by kjdon, 8 years ago

the property file to look up has changed with the new rearrangement of servie rack property files

  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
RevLine 
[3340]1package org.greenstone.gsdl3.action;
2
[25986]3import java.io.Serializable;
[3340]4import java.util.HashMap;
[4857]5import java.util.HashSet;
[3340]6
[25986]7import org.apache.log4j.Logger;
8import org.greenstone.gsdl3.util.GSParams;
9import org.greenstone.gsdl3.util.GSPath;
10import org.greenstone.gsdl3.util.GSXML;
11import org.greenstone.gsdl3.util.GSXSLT;
12import org.greenstone.gsdl3.util.UserContext;
[28382]13import org.w3c.dom.Document;
[25986]14import org.w3c.dom.Element;
15import org.w3c.dom.Node;
16import org.w3c.dom.NodeList;
[13124]17
[3568]18/** action class for queries */
[24987]19public class QueryAction extends Action
20{
[13124]21
[29557]22 public static final String HITS_PER_PAGE = "hitsPerPage";
[24987]23 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.QueryAction.class.getName());
[29557]24
[24987]25 /**
26 * process - processes a request.
27 */
28 public Node process(Node message_node)
29 {
[28964]30 Element message = GSXML.nodeToElement(message_node);
[28382]31 Document doc = message.getOwnerDocument();
32
[24987]33 // get the request - assume there is only one
34 Element request = (Element) GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
[3340]35
[24987]36 // create the return message
[28382]37 Element result = doc.createElement(GSXML.MESSAGE_ELEM);
[24987]38 Element response = basicQuery(request);
[28382]39 result.appendChild(doc.importNode(response, true));
[24987]40 return result;
41 }
[19984]42
[24987]43 /**
44 * a generic query handler this gets the service description, does the query
45 * (just passes all the params to the service, then gets the titles for any
46 * results
47 */
48 protected Element basicQuery(Element request)
49 {
50 // the result
[28382]51 Document doc = request.getOwnerDocument();
52 Element page_response = doc.createElement(GSXML.RESPONSE_ELEM);
[11013]53
[24987]54 // extract the params from the cgi-request, and check that we have a coll specified
55 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
[25635]56 HashMap<String, Serializable> params = GSXML.extractParams(cgi_param_list, false);
[19984]57
[24987]58 String request_type = (String) params.get(GSParams.REQUEST_TYPE);
59 String service_name = (String) params.get(GSParams.SERVICE);
60 String collection = (String) params.get(GSParams.COLLECTION);
[29557]61 String lang = request.getAttribute(GSXML.LANG_ATT);
[24987]62 // collection may be null or empty when we are doing cross coll services
63 if (collection == null || collection.equals(""))
64 {
65 collection = null;
66 }
[4080]67
[24993]68 UserContext userContext = new UserContext(request);
[24987]69 String to = service_name;
70 if (collection != null)
71 {
72 to = GSPath.prependLink(to, collection);
73 }
[4080]74
[27145]75 // get the format info - there may be global format info in the collection that searching needs
76 Element format_elem = getFormatInfo(to, userContext);
77 // set the format type
78 format_elem.setAttribute(GSXML.TYPE_ATT, "search");
79 // for now just add to the response
[28382]80 page_response.appendChild(doc.importNode(format_elem, true));
[27145]81
[29557]82 //if (request_type.indexOf("d") != -1)
83 //{
84 // get the service description
[24987]85 // we have been asked for the service description
[28382]86 Element mr_info_message = doc.createElement(GSXML.MESSAGE_ELEM);
87 Element mr_info_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_DESCRIBE, to, userContext);
[24987]88 mr_info_message.appendChild(mr_info_request);
[14946]89
[24987]90 // process the message
91 Element mr_info_response = (Element) this.mr.process(mr_info_message);
92 // the response
[25860]93
[24987]94 Element service_response = (Element) GSXML.getChildByTagName(mr_info_response, GSXML.RESPONSE_ELEM);
[3753]95
[28382]96 Element service_description = (Element) doc.importNode(GSXML.getChildByTagName(service_response, GSXML.SERVICE_ELEM), true);
[29557]97
98
99 // have we been asked to return it as part of the response?
100 if (request_type.indexOf("d") != -1) {
101 page_response.appendChild(service_description);
102 }
103 //}
104 boolean does_paging = false;
105 Element meta_list =(Element) GSXML.getChildByTagName(service_description, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
106 if (meta_list != null) {
107 String value = GSXML.getMetadataValue(meta_list, "does_paging");
108 if (value.equals("true")) {
109 does_paging = true;
110 }
[24987]111 }
[9874]112
[29557]113 if (does_paging == false) {
114 // we will do the paging, so lets add in a hitsPerPage param to the service
115 addHitsParamToService(doc, service_description, lang);
116 }
[24987]117 if (request_type.indexOf("r") == -1)
118 {
119 // just a display request, no actual processing to do
120 //append site metadata
[24993]121 addSiteMetadata(page_response, userContext);
[25128]122 addInterfaceOptions(page_response);
[24987]123 return page_response;
124 }
[5191]125
[24987]126 // check that we have some service params
127 HashMap service_params = (HashMap) params.get("s1");
128 if (service_params == null)
129 { // no query
130 //append site metadata
[24993]131 addSiteMetadata(page_response, userContext);
[25128]132 addInterfaceOptions(page_response);
[24987]133 return page_response;
134 }
[3987]135
[24987]136 // create the query request
[28382]137 Element mr_query_message = doc.createElement(GSXML.MESSAGE_ELEM);
138 Element mr_query_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_PROCESS, to, userContext);
[24987]139 mr_query_message.appendChild(mr_query_request);
[5191]140
[28382]141 Element query_param_list = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
[28964]142 GSXML.addParametersToList(query_param_list, service_params);
[24987]143 mr_query_request.appendChild(query_param_list);
[5191]144
[24987]145 // do the query
146 Element mr_query_response = (Element) this.mr.process(mr_query_message);
[5191]147
[24987]148 // check for errors
149 if (processErrorElements(mr_query_response, page_response))
150 {
151 //append site metadata
[24993]152 addSiteMetadata(page_response, userContext);
[25128]153 addInterfaceOptions(page_response);
[24987]154 return page_response;
155 }
[5191]156
[27145]157 Element query_response = (Element) GSXML.getChildByTagName(mr_query_response, GSXML.RESPONSE_ELEM);
[24987]158 Element query_result_metadata_list = (Element) GSXML.getChildByTagName(query_response, GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
[30049]159
[24987]160 if (query_result_metadata_list == null)
161 {
162 logger.error("No query result metadata.\n");
163 }
164 else
165 { // add it into the page response
[28382]166 page_response.appendChild(doc.importNode(query_result_metadata_list, true));
[24987]167 }
168
169 Element query_term_info_list = (Element) GSXML.getChildByTagName(query_response, GSXML.TERM_ELEM + GSXML.LIST_MODIFIER);
170 if (query_term_info_list == null)
171 {
172 logger.error("No query term information.\n");
173 }
174 else
175 { // add it into the page response
[28382]176 page_response.appendChild(doc.importNode(query_term_info_list, true));
[24987]177 }
178
[25860]179 Element facet_list = (Element) GSXML.getChildByTagName(query_response, GSXML.FACET_ELEM + GSXML.LIST_MODIFIER);
180 if (facet_list == null)
181 {
182 logger.error("No query term information.\n");
183 }
184 else
185 { // add it into the page response
[28382]186 page_response.appendChild(doc.importNode(facet_list, true));
[25860]187 }
188
[24987]189 // check that there are some documents - for now check the list, but later should use a numdocs metadata elem
190 Element document_list = (Element) GSXML.getChildByTagName(query_response, GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
191 // documentList not present if no docs found
192 if (document_list == null)
193 {
194 // add in a dummy doc node list - used by the display. need to think about this
[28382]195 page_response.appendChild(doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER));
[24987]196 //append site metadata
[24993]197 addSiteMetadata(page_response, userContext);
[25128]198 addInterfaceOptions(page_response);
[24987]199 return page_response;
200 }
201
202 // now we check to see if there is metadata already - some search services return predefined metadata. if there is some, don't do a metadata request
203 NodeList doc_metadata = document_list.getElementsByTagName(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
204 if (doc_metadata.getLength() > 0)
205 {
[29557]206 // why are we not paging these results?????
207 // append the doc list to the result
[28382]208 page_response.appendChild(doc.importNode(document_list, true));
[24987]209 //append site metadata
[24993]210 addSiteMetadata(page_response, userContext);
[25128]211 addInterfaceOptions(page_response);
[24987]212 return page_response;
213 }
214
215 // get the metadata elements needed from the format statement if any
[25635]216 HashSet<String> metadata_names = new HashSet<String>();
[24987]217 metadata_names.add("Title");
[27145]218 // we already got the format element earlier
[24987]219 if (format_elem != null)
220 {
[27145]221 getRequiredMetadataNames(format_elem, metadata_names);
[24987]222 }
223
224 // paging of the results is done here - we filter the list to remove unwanted entries before retrieving metadata
[29557]225 Element filtered_doc_list;
226 if (does_paging) {
227 filtered_doc_list = (Element)doc.importNode(document_list, true);
228 } else {
229 filtered_doc_list = filterDocList(doc, params, service_params, document_list);
230 }
[24987]231 // do the metadata request on the filtered list
[28382]232 Element mr_metadata_message = doc.createElement(GSXML.MESSAGE_ELEM);
[24987]233 to = "DocumentMetadataRetrieve";
234 if (collection != null)
235 {
236 to = GSPath.prependLink(to, collection);
237 }
[28382]238 Element mr_metadata_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_PROCESS, to, userContext);
[24987]239 mr_metadata_message.appendChild(mr_metadata_request);
240
241 // just get all for now - the receptionist should perhaps pass in some
242 // metadata that it wants, and QueryAction should look through the format stuff to see if there is any other?
243
[26026]244 Element extraMetaListElem = (Element) GSXML.getChildByTagName(request, GSXML.EXTRA_METADATA + GSXML.LIST_MODIFIER);
245 if(extraMetaListElem != null)
246 {
247 NodeList extraMetaList = extraMetaListElem.getElementsByTagName(GSXML.EXTRA_METADATA);
248 for(int i = 0; i < extraMetaList.getLength(); i++)
249 {
250 metadata_names.add(((Element)extraMetaList.item(i)).getAttribute(GSXML.NAME_ATT));
251 }
252 }
253
[28382]254 Element dm_param_list = createMetadataParamList(doc,metadata_names);
[24987]255
256 mr_metadata_request.appendChild(dm_param_list);
257
258 // add in the doc node list too
259 mr_metadata_request.appendChild(filtered_doc_list);
260
261 Element mr_metadata_response = (Element) this.mr.process(mr_metadata_message);
[25986]262
[30049]263 Element query_result_snippet_list = (Element) GSXML.getChildByTagName(query_response, GSXML.HL_SNIPPET_ELEM + GSXML.LIST_MODIFIER);
264
[24987]265 // check for errors
266 processErrorElements(mr_metadata_response, page_response);
267
268 Element metadata_response = (Element) GSXML.getChildByTagName(mr_metadata_response, GSXML.RESPONSE_ELEM);
269
270 Element query_result_document_list = (Element) GSXML.getChildByTagName(metadata_response, GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
[30049]271
[24987]272 if (query_result_document_list != null)
273 {
[28382]274 page_response.appendChild(doc.importNode(query_result_document_list, true));
[30094]275 if (query_result_snippet_list != null)
276 {
277 page_response.appendChild(doc.importNode(query_result_snippet_list,true));
278 }
[24987]279 }
[30049]280
[29557]281 //logger.debug("Query page:\n" + this.converter.getPrettyString(page_response));
[24987]282 //append site metadata
[24993]283 addSiteMetadata(page_response, userContext);
[25128]284 addInterfaceOptions(page_response);
[24987]285 return page_response;
[5191]286 }
287
[24987]288 /** this filters out some of the doc results for result paging */
[28382]289 protected Element filterDocList(Document doc, HashMap<String, Serializable> params, HashMap service_params, Element orig_doc_list)
[24987]290 {
291
[29557]292 String hits_pp = (String) service_params.get(HITS_PER_PAGE);
293
[24987]294 int hits = 20;
295 if (hits_pp != null && !hits_pp.equals(""))
296 {
[29557]297 if (hits_pp.equals("all")) {
298 hits = -1;
299 } else {
[24987]300 try
301 {
302 hits = Integer.parseInt(hits_pp);
303 }
304 catch (Exception e)
305 {
306 hits = 20;
307 }
[29557]308 }
[24987]309 }
310 if (hits == -1)
311 { // all
[28382]312 return (Element) doc.importNode(orig_doc_list, true);
[24987]313 }
314 NodeList result_docs = orig_doc_list.getElementsByTagName(GSXML.DOC_NODE_ELEM);
315
316 int num_docs = result_docs.getLength();
317 if (num_docs <= hits)
318 {
319 // too few docs to do paging
[28382]320 return (Element) doc.importNode(orig_doc_list, true);
[24987]321 }
322
323 // now we need our own doc list
[28382]324 Element result_list = doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
[24987]325
326 String start_p = (String) service_params.get("startPage");
327 if (start_p == null)
328 {
329 start_p = (String) params.get("startPage");
330 }
331
332 int start = 1;
333 if (start_p != null && !start_p.equals(""))
334 {
335 try
336 {
337 start = Integer.parseInt(start_p);
338 }
339 catch (Exception e)
340 {
341 start = 1;
342 }
343 }
344 int start_from = (start - 1) * hits;
345 int end_at = (start * hits) - 1;
346
347 if (start_from > num_docs)
348 {
349 // something has gone wrong
350 return result_list;
351 }
352
353 if (end_at > num_docs)
354 {
355 end_at = num_docs - 1;
356 }
357 // now we finally have the docs numbers to use
358 for (int i = start_from; i <= end_at; i++)
359 {
[28382]360 result_list.appendChild(doc.importNode(result_docs.item(i), true));
[24987]361 }
362
363 return result_list;
[5191]364 }
365
[29557]366 protected boolean addHitsParamToService(Document doc, Element service_description, String lang) {
367 Element param_list = (Element)GSXML.getChildByTagName(service_description, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
[30476]368 Element param = GSXML.createParameterDescription(doc, HITS_PER_PAGE, getTextString("param." + HITS_PER_PAGE, lang, "ServiceRack", null), GSXML.PARAM_TYPE_INTEGER, "20", null, null);
[29557]369 Element query_param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, "query");
370 if (query_param != null) {
371 param_list.insertBefore(param, query_param);
372 } else {
373 param_list.appendChild(param);
374 }
375 return true;
376 }
[3340]377}
Note: See TracBrowser for help on using the repository browser.