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

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

Fixing Greenstone 3's use (or lack thereof) of generics, this was done automatically so we may want to change it over time. This change will also auto-format any files that have not already been formatted.

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