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

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

Add the facet list to the page if we get one

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